java 8 stream reduce详解和误区
文章目錄
- 簡介
- reduce詳解
- 總結
java 8 stream reduce詳解和誤區
簡介
Stream API提供了一些預定義的reduce操作,比如count(), max(), min(), sum()等。如果我們需要自己寫reduce的邏輯,則可以使用reduce方法。
本文將會詳細分析一下reduce方法的使用,并給出具體的例子。
reduce詳解
Stream類中有三種reduce,分別接受1個參數,2個參數,和3個參數,首先來看一個參數的情況:
Optional<T> reduce(BinaryOperator<T> accumulator);該方法接受一個BinaryOperator參數,BinaryOperator是一個@FunctionalInterface,需要實現方法:
R apply(T t, U u);accumulator告訴reduce方法怎么去累計stream中的數據。
舉個例子:
List<Integer> intList = Arrays.asList(1,2,3);Optional<Integer> result1=intList.stream().reduce(Integer::sum);log.info("{}",result1);上面的例子輸出結果:
com.flydean.ReduceUsage - Optional[6]一個參數的例子很簡單。這里不再多說。
接下來我們再看一下兩個參數的例子:
T reduce(T identity, BinaryOperator<T> accumulator);這個方法接收兩個參數:identity和accumulator。多出了一個參數identity。
也許在有些文章里面有人告訴你identity是reduce的初始化值,可以隨便指定,如下所示:
Integer result2=intList.stream().reduce(100, Integer::sum);log.info("{}",result2);上面的例子,我們計算的值是106。
如果我們將stream改成parallelStream:
Integer result3=intList.parallelStream().reduce(100, Integer::sum);log.info("{}",result3);得出的結果就是306。
為什么是306呢?因為在并行計算的時候,每個線程的初始累加值都是100,最后3個線程加出來的結果就是306。
并行計算和非并行計算的結果居然不一樣,這肯定不是JDK的問題,我們再看一下JDK中對identity的說明:
identity必須是accumulator函數的一個identity,也就是說必須滿足:對于所有的t,都必須滿足 accumulator.apply(identity, t) == t
所以這里我們傳入100是不對的,因為sum(100+1)!= 1。
這里sum方法的identity只能是0。
如果我們用0作為identity,則stream和parallelStream計算出的結果是一樣的。這就是identity的真正意圖。
下面再看一下三個參數的方法:
<U> U reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator<U> combiner);和前面的方法不同的是,多了一個combiner,這個combiner用來合并多線程計算的結果。
同樣的,identity需要滿足combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t)
大家可能注意到了為什么accumulator的類型是BiFunction而combiner的類型是BinaryOperator?
public interface BinaryOperator<T> extends BiFunction<T,T,T>BinaryOperator是BiFunction的子接口。BiFunction中定義了要實現的apply方法。
其實reduce底層方法的實現只用到了apply方法,并沒有用到接口中其他的方法,所以我猜測這里的不同只是為了簡單的區分。
總結
雖然reduce是一個很常用的方法,但是大家一定要遵循identity的規范,并不是所有的identity都是合適的。
本文的例子https://github.com/ddean2009/learn-java-streams/tree/master/stream-reduce
更多精彩內容且看:
- 區塊鏈從入門到放棄系列教程-涵蓋密碼學,超級賬本,以太坊,Libra,比特幣等持續更新
- Spring Boot 2.X系列教程:七天從無到有掌握Spring Boot-持續更新
- Spring 5.X系列教程:滿足你對Spring5的一切想象-持續更新
- java程序員從小工到專家成神之路(2020版)-持續更新中,附詳細文章教程
歡迎關注我的公眾號:程序那些事,更多精彩等著您!
更多內容請訪問 www.flydean.com
總結
以上是生活随笔為你收集整理的java 8 stream reduce详解和误区的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java stream中Collecto
- 下一篇: 怎么在java中创建一个自定义的coll