java 8 stream reduce详解和误区
目录
java 8 stream reduce详解和误区 简介Stream API提供了一些预定义的reduce操作,比如count(),max(),min(),sum()等。如果我们需要自己写reduce的逻辑,则可以使用reduce方法。 本文将会详细分析一下reduce方法的使用,并给出具体的例子。 reduce详解Stream类中有三种reduce,分别接受1个参数,2个参数,和3个参数,首先来看一个参数的情况:
该方法接受一个BinaryOperator参数,BinaryOperator是一个@FunctionalInterface,需要实现方法:
accumulator告诉reduce方法怎么去累计stream中的数据。 举个例子:
上面的例子输出结果:
一个参数的例子很简单。这里不再多说。 接下来我们再看一下两个参数的例子:
这个方法接收两个参数:identity和accumulator。多出了一个参数identity。 也许在有些文章里面有人告诉你identity是reduce的初始化值,可以随便指定,如下所示:
上面的例子,我们计算的值是106。 如果我们将stream改成parallelStream:
得出的结果就是306。 为什么是306呢?因为在并行计算的时候,每个线程的初始累加值都是100,最后3个线程加出来的结果就是306。 并行计算和非并行计算的结果居然不一样,这肯定不是JDK的问题,我们再看一下JDK中对identity的说明:
所以这里我们传入100是不对的,因为sum(100+1)!= 1。 这里sum方法的identity只能是0。 如果我们用0作为identity,则stream和parallelStream计算出的结果是一样的。这就是identity的真正意图。 下面再看一下三个参数的方法:
和前面的方法不同的是,多了一个combiner,这个combiner用来合并多线程计算的结果。
大家可能注意到了为什么accumulator的类型是BiFunction而combiner的类型是BinaryOperator?
BinaryOperator是BiFunction的子接口。BiFunction中定义了要实现的apply方法。 其实reduce底层方法的实现只用到了apply方法,并没有用到接口中其他的方法,所以我猜测这里的不同只是为了简单的区分。 总结虽然reduce是一个很常用的方法,但是大家一定要遵循identity的规范,并不是所有的identity都是合适的。 本文的例子https://github.com/ddean2009/learn-java-streams/tree/master/stream-reduce
(编辑:北几岛) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |