jdk8 Stream介绍
java.util.stream.Stream的操作分类,如表所示:
Stream的操作可以分为两大类
- 中间操作(Intermediate operations): 对操作进行了记录,但是不立即执行。中间操作又可以分为
1.1 无状态(Stateless)操作: 元素的处理不受之前元素的影响; 1.2 有状态(Stateful)操作: 只有拿到所有元素之后才能继续下去。 |
- 结束操作(Terminal operations):触发实际的计算(即惰性求值)。结束操作又可以分为
2.1 短路操作(short-circuiting): 指遇到某些符合条件的元素就可以得到最终结果; 2.2 非短路操作:必须处理所有元素才能得到最终结果。 |
1. Stream的操作对象
1.1 数组
1.2 Collection的实现类
1.3 Map的实现类
|
2.常见的Stream操作方法
2.1. Intermediate operations 的无状态(Stateless)操作方法
2.1.1 filter方法
顾名思义,可以对元素进行过滤操作,过滤规则由Predicate接口的test方法决定:
Predicate接口是函数式接口(只有一个未实现方法),可以使用方法引用。举例:
2.1.2 map方法
2.1.3 peek方法
对Stream的每个元素执行额外的操作,Consumer接口声明了void返回值的accept方法:
|
flatMap方法会先将一个T类型的元素通过mapper映射成一个R元素类型的Stream,最后将这些Stream组合起来返回最终的R类型Stream;举例:
flatMap 把input的 Stream 中的层级结构扁平化,就是将最底层元素抽出来放到一起,最终output 的新 Stream 里面已经没有 List 了,都是直接的数字。 flatMap方法一般使用在元素类型本来就是数组或集合类的场景。 |
2.1.5 mapToInt&mapToLong&mapToDouble方法
|
这三个方法是map方法的变种。
2.2. Intermediate operations 的有状态(Stateful)操作方法
2.2.1 sorted方法
返回一个排序过的Stream。
2.2.2 distinct方法
返回由不同元素(根据Object的equals(Object)方法)组成的Stream。
2.2.3 limit方法
只保留Stream的前maxSize个元素。
2.2.4 skip方法
|
2.3 Terminal operations的非短路操作方法
|
|
对于每个元素执行一次最终操作,在并发Stream中,map方法不能保证元素处理顺序;
2.3.2 forEachOrdered方法
|
与forEach方法类似,不同之处在于可以按顺序进行最终操作;
2.3.3 toArray方法
|
将Stream转化为数组,其中第二个toArray方法的函数式接口IntFunction可以得到不同类型数组而不是Object数组,提供了一个apply方法
|
一般是传入一个数组构造函数的方法引用,举例:
|
2.3.4 reduce方法
|
BinaryOperator是函数式接口BiFunction的子类,提供了apply方法:
|
对于前2个reduce方法,所有的Stream元素都通过apply方法进行处理,第一个参数t是上一次apply的处理结果,第二个参数u则是将要进行处理的元素。其中第一个reduce方法从初始值identity开始进行,返回值是T类型;第二个reduce方法从第一个Stream元素开始进行,返回值是Optional<T>类型。
举例:
|
第3种reduce方法解决了类型转换的问题(前两种reduce方法的元素类型和返回结果类型是相同的)。第一个参数即初始值identity是U类型的;第二个参数BiFunction<U, ? super T, U> accumulator实现了处理和类型转换;第三个参数BinaryOperator<U> combiner是对并行Stream(numList.parallelStream()//得到并行Stream)中不同线程处理得到的部分结果进行结合,返回最终结果(普通条件下不会触发combiner)。
举例:
|
2.3.5 collect方法
|
Supplier接口定义为:
|
BiConsumer接口定义为:
|
第1个collect方法相当于做了如下处理:
|
举例:
|
第2个collect方法一般是配合Collectors类进行使用的,举例:
|
第二种collect方法的使用场景比较多,更为常见。
2.3.5 max&min&count方法
不介绍了,请看jdk源码
2.4 Terminal operations的短路(short-cutting)操作方法
|
|
只要任意元素满足Predicate就返回true;
所有元素都满足Predicate则返回true;
所有元素都不满足Predicate则返回true。
2.4.2 findFirst&findAny方法
|
findFirst:返回Stream中的第一个元素;
findAny:返回的是最快处理完的那个线程的数据(?)。
3. 关于Stream的并发处理
在BaseStream接口中,定义了获取 并发/顺序 Stream的方法
|