技术编程5万字:Stream和Lambda表达式最佳实践2( 五 )


下面再看一下三个参数的方法: U reduce(U identity,BiFunction
accumulator,BinaryOperator combiner);复制代码
和前面的方法不同的是 , 多了一个combiner , 这个combiner用来合并多线程计算的结果 。 同样的 , identity需要满足combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t)
大家可能注意到了为什么accumulator的类型是BiFunction而combiner的类型是BinaryOperator?public interface BinaryOperator extends BiFunction
复制代码
BinaryOperator是BiFunction的子接口 。 BiFunction中定义了要实现的apply方法 。
其实reduce底层方法的实现只用到了apply方法 , 并没有用到接口中其他的方法 , 所以我猜测这里的不同只是为了简单的区分 。
虽然reduce是一个很常用的方法 , 但是大家一定要遵循identity的规范 , 并不是所有的identity都是合适的 。 12. stream中的Spliterator
Spliterator是在java 8引入的一个接口 , 它通常和stream一起使用 , 用来遍历和分割序列 。
只要用到stream的地方都需要Spliterator , 比如List , Collection , IO channel等等 。
我们先看一下Collection中stream方法的定义:default Stream stream() {return StreamSupport.stream(spliterator(), false);}复制代码default Stream parallelStream() {return StreamSupport.stream(spliterator(), true);}复制代码
我们可以看到 , 不管是并行stream还是非并行stream , 都是通过StreamSupport来构造的 , 并且都需要传入一个spliterator的参数 。
好了 , 我们知道了spliterator是做什么的之后 , 看一下它的具体结构:
技术编程5万字:Stream和Lambda表达式最佳实践2
本文插图
spliterator有四个必须实现的方法 , 我们接下来进行详细的讲解 。 12.1 tryAdvance
tryAdvance就是对stream中的元素进行处理的方法 , 如果元素存在 , 则对他进行处理 , 并返回true , 否则返回false 。
如果我们不想处理stream后续的元素 , 则在tryAdvance中返回false即可 , 利用这个特征 , 我们可以中断stream的处理 。 这个例子我将会在后面的文章中讲到 。 12.2 trySplit
trySplit尝试对现有的stream进行分拆 , 一般用在parallelStream的情况 , 因为在并发stream下 , 我们需要用多线程去处理stream的不同元素 , trySplit就是对stream中元素进行分拆处理的方法 。
理想情况下trySplit应该将stream拆分成数目相同的两部分才能最大提升性能 。 12.3 estimateSize
estimateSize表示Spliterator中待处理的元素 , 在trySplit之前和之后一般是不同的 , 后面我们会在具体的例子中说明 。 12.4 characteristics
characteristics表示这个Spliterator的特征 , Spliterator有8大特征:public static final int ORDERED= 0x00000010;//表示元素是有序的(每一次遍历结果相同)public static final int DISTINCT= 0x00000001;//表示元素不重复public static final int SORTED= 0x00000004;//表示元素是按一定规律进行排列(有指定比较器)public static final int SIZED= 0x00000040;//表示大小是固定的public static final int NONNULL= 0x00000100;//表示没有null元素public static final int IMMUTABLE= 0x00000400;//表示元素不可变public static final int CONCURRENT = 0x00001000;//表示迭代器可以多线程操作public static final int SUBSIZED= 0x00004000;//表示子Spliterators都具有SIZED特性复制代码
一个Spliterator可以有多个特征 , 多个特征进行or运算 , 最后得到最终的characteristics 。 12.5 举个例子


推荐阅读