【java API】【stream】reduce()、collect()、 forEach()的用法和区别以及Collector类的使用

背景:读IBM stream系列第三篇时有提到这三个操作是非短路操作,对这三个的用法和区别不了解,这里总结下。

【reduce】参考链接一将reduce()函数的三种形式及涉及的参数类型讲的很清楚,这里只提取出关键点,建议看下该链接。

在并行处理情况下,传入给Reduce等方法的集合类,需要是线程安全的,否则执行结果会与预期结果不一样。reduce函数功能是根据一定的规则将Stream中的元素进行计算后返回一个唯一的值。其有三种重载形式如下。

Optional<T> reduce(BinaryOperator<T> accumulator)

T reduce(T identity, BinaryOperator<T> accumulator)(相对于一个参数的形式,增加了初始参数)

<U> U reduce(U identity, BiFunction<U, ? supper T, U> accumulator, BinaryOperator<U> combiner)(相对于两个参数,可用于转变流中的数据类型,增加的第三个参数在并行计算时才生效)

 

Stream.parallel()可以将流设置为并行的,从而使得第三个参数生效。需要注意有几个并行分段,identity就被使用了几次,作为每个分段的初始值,这样会出现意想不到的结果,如求和时,结果与串行差了identity的整数倍。如果第一个参数的类型是ArrayList等对象而非基本数据类型的包装类或者String,则每个并行分段会使用同样的identity引用,不会出现前面求和加倍的事情,但需要注意线程安全,所以最好用线程安全的数据类型,如:Collections.synchronizedList(new ArrayList<String>())。

reduce()的demo链接

【collect】参考链接一

collect含义与Reduce有点相似

<R> R collect(Supplier<R> supplier,
                BiConsumer<R, ? super T> accumulator,
                BiConsumer<R, R> combiner)

supplier:动态的提供初始化的值;创建一个可变的结果容器,对于并行计算,这个方法可能被调用多次,每次返回一个新的对象;

accumulator:类型为BiConsumer,注意这个接口是没有返回值的;它必须将一个元素放入结果容器中

combiner:类型也是BiConsumer,因此也没有返回值。它与三参数的Reduce类型,只是在并行计算时汇总不同线程计算的结果。它的输入是两个结果容器,必须将第二个结果容器中的值全部放入第一个结果容器中

JAVADOC中也在强调结果容器(result container)这个,那是否除集合类型,其结果R也可以是其它类型呢?先看基本类型,由于BiConsumer不会有返回值,如果是基本数据类型或者String,在BiConsumer中加工后的结果都无法在这个函数外体现,因此是没有意义的。那其它非集合类型的Java对象呢?如果对象中包含有集合类型的属性,也是可以处理的;否则,处理上也没有任何意义,combiner对象使用一个Java对象来更新另外一个对象?这种场景很少见。最后原文作者强调reduce或R为集合类型的collect更常用。

collect()的demo链接

【forEach】Stream为接口,of()这个静态方法在Stream中有实现(jdk1.8支持接口中有方法的默认实现),比如Stream.of(T... values)会调用Arrays.stream(values)方法返回实例化的Stream对象。所以要去到Arrays里看看其实现的Stream的forEach方法。可以看到Arrays.stream()使用的StreamSupport.stream()这个静态方法创建的默认为非并行的stream。这个方法会调ReferencePipeline.Head<>来生成Stream实例。ReferencePipeline继承了AbstractPipeline,实例化了Stream接口。forEach方法最终调用的AbstractPipeline的evaluate()。forEach方法参数为Consumer接口,只有一个待实现的accept()方法,传入一个function就会被包装成Consumer。

【Collector】https://www.cnblogs.com/woshimrf/p/java8-learn-collector.html

 

参考链接一(reduce()和collect的用法及区别)

https://blog.csdn.net/icarusliu/article/details/79504602

参考链接二(Stream所属包为java.util.stream)

https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html

参考链接三(reduce()和collect()所属类Stream)

https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值