例如這個練習題,使用reduce和lambda表達式來實現(xiàn)map。
不明白的是reduce第三個參數(shù)的意義,感覺多此一舉
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Stream;
public class MapUsingReduce {
public static <I, O> List<O> map(Stream<I> stream, Function<I, O> mapper) {
return stream.reduce(new ArrayList<O>(), (acc, x) -> {
// We are copying data from acc to new list instance. It is very inefficient,
// but contract of Stream.reduce method requires that accumulator function does
// not mutate its arguments.
// Stream.collect method could be used to implement more efficient mutable reduction,
// but this exercise asks to use reduce method.
List<O> newAcc = new ArrayList<>(acc);
newAcc.add(mapper.apply(x));
return newAcc;
}, (List<O> left, List<O> right) -> {
// We are copying left to new list to avoid mutating it.
List<O> newLeft = new ArrayList<>(left);
newLeft.addAll(right);
return newLeft;
});
}
}
下面是文檔的說明,仍然不明白。。。
<U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)
Performs a reduction on the elements of this stream, using the provided identity, accumulation and combining functions. This is equivalent to:
U result = identity; for (T element : this stream) result = accumulator.apply(result, element) return result;
but is not constrained to execute sequentially.
The identity value must be an identity for the combiner function. This means that for all u, combiner(identity, u) is equal to u. Additionally, the combiner function must be compatible with the accumulator function; for all u and t, the following must hold:
combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t)
望指教,謝謝!
我覺得可以這樣理解
首先理解方法本身的意思:Stream
的reduce
方法,翻譯過來是聚合或者是匯聚成一個的意思,由于Stream
本身就代表著一堆數(shù)據(jù),那stream.reduce()
方法顧名思義就是把一堆數(shù)據(jù)聚合成一個數(shù)據(jù)
理解了reduce
方法的意思,再來看看這個方法掛靠的對象是stream
,是一個流,了解一下流的工作方式:
流底層核心其實是Spliterator
接口的一個實現(xiàn),而這個Spliterator
接口其實本身就是Fork/Join并行框架的一個實現(xiàn),所以歸根結(jié)底要明白流的工作方式,就要明白一下Fork/Join框架的基本思想,即:以遞歸的方式將可以并行的任務拆分成更小的子任務,然后將每個子任務的結(jié)果合并起來生成整體的最后結(jié)果,畫了個草圖如下
理解了方法本身的意思以及流的工作方式,再結(jié)合到一起理解一下stream.reduce()
方法,即用Fork/Join的方式把一堆數(shù)據(jù)聚合成一個數(shù)據(jù),因此可以畫出reduce
方法的運行草圖
結(jié)合草圖,要實現(xiàn)stream.reduce()
方法,必須要告訴JDK
你有什么需求數(shù)據(jù)要匯聚?(Stream已經(jīng)提供了數(shù)據(jù)源,對應上面草圖的A元素)
最后要匯聚成怎樣的一個數(shù)據(jù)類型(對應reduce方法的參數(shù)一,對應上面草圖的B元素)
如何將需求數(shù)據(jù)處理或轉(zhuǎn)化成一個匯聚數(shù)據(jù)(對應reduce方法的參數(shù)二,對應上面草圖的匯聚方式1)
如何將多個匯聚數(shù)據(jù)進行合并(對應reduce方法的參數(shù)三,對應上面草圖的匯聚方式2)
再結(jié)合你給的map方法,其實是要把O
類數(shù)據(jù)的流,最后轉(zhuǎn)化為一個I
類數(shù)據(jù)的List,因此按照上面的步驟可以進行對照
你有什么需求數(shù)據(jù)要匯聚?(O
類數(shù)據(jù)流)
最后要匯聚成怎樣的一個數(shù)據(jù)類型(一個集合,new ArrayList()
)
如何將需求數(shù)據(jù)處理或轉(zhuǎn)化成一個匯聚數(shù)據(jù)(根據(jù)mapper把O
轉(zhuǎn)化為I
,再用List.add
方法)
如何將多個匯聚數(shù)據(jù)進行合并(兩個集合合并,用List.addAll()
)
最后補充一點,若是你的參數(shù)真是Stream<I> stream
和Function<I, O> mapper
,建議不要用reduce
方法,這么寫可能會更好一點
public static <I, O> List<O> map(Stream<I> stream, Function<I, O> mapper) {
return stream.map(mapper).collect(Collectors.toList());
}
樓上說的不錯,但是補充一點:
BinaryOperator是供多線程使用的,如果不在Stream中聲明使用多線程,就不會使用子任務,自然也不會調(diào)用到該方法。另外多線程下使用BinaryOperator的時候是需要考慮線程安全的問題。
另外自問自答下為什么需要BinaryOperator
因為這個重載的方法和其他兩個不相同,允許改變返回值,所以返回值并不一定是Collection的子類;因此必須顯示的聲明如何拼接兩個子任務產(chǎn)生的結(jié)果。
但是java8函數(shù)編程一書中這一題返回的結(jié)果恰好是List,就造成了BinaryOperator并不需要的假象。
個人愚見,如有不對,懇請扶正。
北大青鳥APTECH成立于1999年。依托北京大學優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國家
北大青鳥中博軟件學院創(chuàng)立于2003年,作為華東區(qū)著名互聯(lián)網(wǎng)學院和江蘇省首批服務外包人才培訓基地,中博成功培育了近30000名軟件工程師走向高薪崗位,合作企業(yè)超4
中公教育集團創(chuàng)建于1999年,經(jīng)過二十年潛心發(fā)展,已由一家北大畢業(yè)生自主創(chuàng)業(yè)的信息技術(shù)與教育服務機構(gòu),發(fā)展為教育服務業(yè)的綜合性企業(yè)集團,成為集合面授教學培訓、網(wǎng)
達內(nèi)教育集團成立于2002年,是一家由留學海歸創(chuàng)辦的高端職業(yè)教育培訓機構(gòu),是中國一站式人才培養(yǎng)平臺、一站式人才輸送平臺。2014年4月3日在美國成功上市,融資1
浪潮集團項目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺面向?qū)ο箝_發(fā)經(jīng)驗,技術(shù)功底深厚。 授課風格 授課風格清新自然、條理清晰、主次分明、重點難點突出、引人入勝。
曾工作于聯(lián)想擔任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔任項目經(jīng)理從事移動互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍懿科技有限責任公司從事總經(jīng)理職務負責iOS教學及管理工作。
精通HTML5和CSS3;Javascript及主流js庫,具有快速界面開發(fā)的能力,對瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁制作和網(wǎng)頁游戲開發(fā)。
具有10 年的Java 企業(yè)應用開發(fā)經(jīng)驗。曾經(jīng)歷任德國Software AG 技術(shù)顧問,美國Dachieve 系統(tǒng)架構(gòu)師,美國AngelEngineers Inc. 系統(tǒng)架構(gòu)師。