JAVA研发狄仁杰 5万字:Stream和Lambda表达式最佳实践2( 五 )


大家可能注意到了为什么accumulator的类型是BiFunction而combiner的类型是BinaryOperator?publicinterfaceBinaryOperatorextendsBiFunction
复制代码
BinaryOperator是BiFunction的子接口 。 BiFunction中定义了要实现的apply方法 。
其实reduce底层方法的实现只用到了apply方法 , 并没有用到接口中其他的方法 , 所以我猜测这里的不同只是为了简单的区分 。
虽然reduce是一个很常用的方法 , 但是大家一定要遵循identity的规范 , 并不是所有的identity都是合适的 。 12.stream中的Spliterator
Spliterator是在java8引入的一个接口 , 它通常和stream一起使用 , 用来遍历和分割序列 。
只要用到stream的地方都需要Spliterator , 比如List , Collection , IOchannel等等 。
我们先看一下Collection中stream方法的定义:defaultStreamstream(){returnStreamSupport.stream(spliterator(),false);}复制代码defaultStreamparallelStream(){returnStreamSupport.stream(spliterator(),true);}复制代码
我们可以看到 , 不管是并行stream还是非并行stream , 都是通过StreamSupport来构造的 , 并且都需要传入一个spliterator的参数 。
好了 , 我们知道了spliterator是做什么的之后 , 看一下它的具体结构:
JAVA研发狄仁杰 5万字:Stream和Lambda表达式最佳实践2
文章图片
spliterator有四个必须实现的方法 , 我们接下来进行详细的讲解 。 12.1tryAdvance
tryAdvance就是对stream中的元素进行处理的方法 , 如果元素存在 , 则对他进行处理 , 并返回true , 否则返回false 。
如果我们不想处理stream后续的元素 , 则在tryAdvance中返回false即可 , 利用这个特征 , 我们可以中断stream的处理 。 这个例子我将会在后面的文章中讲到 。 12.2trySplit
trySplit尝试对现有的stream进行分拆 , 一般用在parallelStream的情况 , 因为在并发stream下 , 我们需要用多线程去处理stream的不同元素 , trySplit就是对stream中元素进行分拆处理的方法 。
理想情况下trySplit应该将stream拆分成数目相同的两部分才能最大提升性能 。 12.3estimateSize
estimateSize表示Spliterator中待处理的元素 , 在trySplit之前和之后一般是不同的 , 后面我们会在具体的例子中说明 。 12.4characteristics
characteristics表示这个Spliterator的特征 , Spliterator有8大特征:publicstaticfinalintORDERED=0x00000010;//表示元素是有序的(每一次遍历结果相同)publicstaticfinalintDISTINCT=0x00000001;//表示元素不重复publicstaticfinalintSORTED=0x00000004;//表示元素是按一定规律进行排列(有指定比较器)publicstaticfinalintSIZED=0x00000040;//表示大小是固定的publicstaticfinalintNONNULL=0x00000100;//表示没有null元素publicstaticfinalintIMMUTABLE=0x00000400;//表示元素不可变publicstaticfinalintCONCURRENT=0x00001000;//表示迭代器可以多线程操作publicstaticfinalintSUBSIZED=0x00004000;//表示子Spliterators都具有SIZED特性复制代码
一个Spliterator可以有多个特征 , 多个特征进行or运算 , 最后得到最终的characteristics 。 12.5举个例子
上面我们讨论了Spliterator一些关键方法 , 现在我们举一个具体的例子:@AllArgsConstructor@DatapublicclassCustBook{privateStringname;}复制代码
先定义一个CustBook类 , 里面放一个name变量 。
定义一个方法 , 来生成一个CustBook的list:publicstaticList
generateElements(){returnStream.generate(()->newCustBook("custbook")).limit(1000).collect(Collectors.toList());}复制代码
我们定义一个call方法 , 在call方法中调用了tryAdvance方法 , 传入了我们自定义的处理方法 。 这里我们修改book的name,并附加额外的信息 。 publicStringcall(Spliterator


推荐阅读