Java SE 8 中的流

  |   0 评论   |   0 浏览

Java SE 8 的流采用的是函数式编程范式。

流是什么

流的特性:

  1. 流代表有限或者无限个数据元素的序列。
  2. 流不是数据结构,它不存储元素。这些元素可能存储在底层的集合中,或者是桉树生成的。
  3. 流是有关算法和计算的,它更像一个高级版本的Iterator,但它不需要我们显式地遍历每个元素并执行某些操作。我们只需要指定“做什么”,而不需要操心“怎么做”。
  4. 流的操作不会修改其数据源,执行某个操作后会生成新的流。
  5. 流支持并行,其并行操作依赖于Java7中引入的Fork/Join框架(JSR166y)来拆分任务和加速处理过程。

流的创建

创建流的常见方式:

From a Collection via the stream() and parallelStream() methods;
From an array via Arrays.stream(Object[]);
From static factory methods on the stream classes, such as Stream.of(Object[]), IntStream.range(int, int) or Stream.iterate(Object, UnaryOperator);
The lines of a file can be obtained from BufferedReader.lines();
Streams of file paths can be obtained from methods in Files;
Streams of random numbers can be obtained from Random.ints();
Numerous other stream-bearing methods in the JDK, including BitSet.stream(), Pattern.splitAsStream(java.lang.CharSequence), and JarFile.stream().

示例

1// 单独的值
2Stream stream = Stream.of("a", "b", "c");
3// 数组
4String [] strArray = new String[] {"a", "b", "c"};
5stream = Stream.of(strArray);
6stream = Arrays.stream(strArray);
7// 集合
8List<String> list = Arrays.asList(strArray);
9stream = list.stream();

流操作和管道

流操作分为两种

  • 中间操作(Intermediate):对流中元素的操作进行转换(比如:映射、过滤等),一个流可以后面跟随零个或多个 intermediate 操作。它会返回一个新的流,交给下一个操作使用。这类操作都是惰性化的(lazy)。
  • 终止操作(Terminal):通常会产生一个结果,这个操作之后,流将不能再被操作。

流管道(Stream Pipeline):由一个数据源(比如:集合,数组),零到多个Intermediate操作,以及一个Terminal操作构成。

中间操作

中间操作又可以细分为:有状态(stateful)操作和无状态(stateless)操作。

  • 无状态操作(比如:filter()map())不用保留上一个流中元素的状态,每个元素都可以单独处理,互不影响。这种操作是可以并行的。
  • 有状态操作(比如:distinct()sorted())则必须处理整个流的元素之后,才能产生一个最终的结果。这种操作是不能并行的。

示例

 1// 过滤和映射
 2Stream<String> someWords = Stream.of("hello","java","world","stream","map");
 3someWords.filter(w -> w.length() < 5)
 4         .map(String::toUpperCase)
 5         .collect(Collectors.joining(","));
 6// 去重、排序、转换为数组
 7Stream<Integer> nums = Stream.of(5, 3, 7, 2, 1, 6, 5);
 8nums.distinct()
 9    .sorted()
10    .toArray();
11// 限定元素个数
12Stream<Double> randoms = Stream.generate(Math::random).limit(100);

终止操作

终止操作也可分为两类:

  • 归约(reduction)操作, 包括reduce()collect()以及sum()max()count()等。
  • 遍历操作,包括forEach()forEachOrdered()

示例

 1// 求和
 2List<Integer> numbers = Arrays.asList(new Integer[]{5, 3, 7, 2, 1, 6, 5});
 3int sum = numbers.stream().reduce(0, Integer::sum);
 4
 5// 按照国家分组,并将每个国家及其对应的locale集合放到map中
 6Stream<Locale> locales= Stream.of(Locale.getAvailableLocales());
 7Map<String, Set<Locale>> countryToLocaleSet = locales.collect(Collectors.groupingBy(
 8        Locale::getCountry, toSet()
 9));
10
11// 最大的元素
12Stream<String> someWords = Stream.of("hello","java","world","stream","map");
13Optional<String> largest = someWords.max(String::compareToIgnoreCase);
14
15// 第一个元素
16Stream<Integer> nums = Stream.of(5, 3, 7, 2, 1, 6, 5);
17Optional<Integer> first = nums.findFirst();

相关资料

https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/index.html