获取一个数据源(source)→ 数据转换→执行操做获取想要的结果,每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象(能够有屡次转换),这就容许对其操做能够像链条同样排列,变成一个管道,html
Stream操做还有两个基础的特征:java
对 Stream 的使用就是实现一个 filter-map-reduce 过程,产生一个最终结果,或者致使一个反作用(side effect)。api
接下来,当把一个数据结构包装成 Stream 后,就要开始对里面的元素进行各种操做了。常见的操做能够归类以下。数组
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered数据结构
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator多线程
anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limitide
Stream<List<Integer>> inputStream = Stream.of( Arrays.asList(1), Arrays.asList(2, 3), Arrays.asList(4, 5, 6) ); Stream<Integer> outputStream = inputStream. flatMap((childList) -> childList.stream());
flatMap 把 input Stream 中的层级结构扁平化,就是将最底层元素抽出来放到一块儿,最终 output 的新 Stream 里面已经没有 List 了,都是直接的数字。性能
List<String> output = reader.lines(). flatMap(line -> Stream.of(line.split(REGEXP))). filter(word -> word.length() > 0). collect(Collectors.toList());
这段代码首先把每行的单词用 flatMap 整理到新的 Stream,而后保留长度不为 0 的,就是整篇文章中的所有单词了。优化
forEachui
forEach 方法接收一个 Lambda 表达式,而后在 Stream 的每个元素上执行该表达式。
// Java 8 roster.stream() .filter(p -> p.getGender() == Person.Sex.MALE) .forEach(p -> System.out.println(p.getName())); // Pre-Java 8 for (Person p : roster) { if (p.getGender() == Person.Sex.MALE) { System.out.println(p.getName()); } }
须要注意,forEach 是 terminal 操做,所以它执行后,Stream 的元素就被“消费”掉了,你没法对一个 Stream 进行两次 terminal 运算。forEach 不能修改本身包含的本地变量值,也不能用 break/return 之类的关键字提早结束循环。
reduce
这个方法的主要做用是把 Stream 元素组合起来。它提供一个起始值(种子),而后依照运算规则(BinaryOperator),和前面 Stream 的第一个、第二个、第 n 个元素组合。
// 字符串链接,concat = "ABCD" String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat); // 求最小值,minValue = -3.0 double minValue = Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX_VALUE, Double::min); // 求和,sumValue = 10, 有起始值 int sumValue = Stream.of(1, 2, 3, 4).reduce(0, Integer::sum); // 求和,sumValue = 10, 无起始值 sumValue = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get(); // 过滤,字符串链接,concat = "ace" concat = Stream.of("a", "B", "c", "D", "e", "F"). filter(x -> x.compareTo("Z") > 0). reduce("", String::concat);
上面代码例如第一个示例的 reduce(),第一个参数(空白字符)即为起始值,第二个参数(String::concat)为 BinaryOperator。这类有起始值的 reduce() 都返回具体的对象。而对于第四个示例没有起始值的 reduce(),因为可能没有足够的元素,返回的是 Optional,请留意这个区别。
min/max/distinct
min 和 max 的功能也能够经过对 Stream 元素先排序,再 findFirst 来实现,但前者的性能会更好,为 O(n),而 sorted 的成本是 O(n log n)。
Match
Stream 有三个 match 方法,从语义上说:
它们都不是要遍历所有元素才能返回结果。例如 allMatch 只要一个元素不知足条件,就 skip 剩下的全部元素,返回 false。对清单 13 中的 Person 类稍作修改,加入一个 age 属性和 getAge 方法。
List<Person> persons = new ArrayList(); persons.add(new Person(1, "name" + 1, 10)); persons.add(new Person(2, "name" + 2, 21)); persons.add(new Person(3, "name" + 3, 34)); persons.add(new Person(4, "name" + 4, 6)); persons.add(new Person(5, "name" + 5, 55)); boolean isAllAdult = persons.stream(). allMatch(p -> p.getAge() > 18); System.out.println("All are adult? " + isAllAdult); boolean isThereAnyChild = persons.stream(). anyMatch(p -> p.getAge() < 12); System.out.println("Any child? " + isThereAnyChild);
输出结果:
All are adult? false
Any child? true
Collectors 类实现了不少归约操做,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
System.out.println("筛选列表: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("合并字符串: " + mergedString);
Stream 的特性能够概括为:
本文转自:https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/index.html