- Java核心技術·卷Ⅱ:高級特性(原書第10版)
- (美)凱S.霍斯特曼
- 1253字
- 2020-10-30 18:10:36
1.12 約簡操作
reduce方法是一種用于從流中計算某個值的通用機制,其最簡單的形式將接受一個二元函數,并從前兩個元素開始持續應用它。如果該函數是求和函數,那么就很容易解釋這種機制:

在上面的情況中,reduce方法會計算v0+v1+v2+…,其中vi是流中的元素。如果流為空,那么該方法會返回一個Optional,因為沒有任何有效的結果。
注意:在上面的情況中,可以寫成reduce(Integer::sum)而不是reduce((x,y)->x+y)。
通常,如果reduce方法有一項約簡操作op,那么該約簡就會產生v0 op v1 op v2 op…,其中我們將函數調用op(vi,vi+1)寫作vi op vi+1。這項操作應該是可結合的:即組合元素時使用的順序不應該成為問題。在數學標記法中,(x op y)op z必須等于x op(y op z)。這使得在使用并行流時,可以執行高效的約簡。
有很多種在實踐中會顯得很有用的可結合操作,例如求和、乘積、字符串連接、取最大值和最小值、求集的并與交等。減法是一個不可結合操作的例子,例如,(6-3)-2≠6-(3-2)。
通常,會有一個幺元值e使得e op x=x,可以使用這個元素作為計算的起點。例如,0是加法的幺元值。然后,可以調用第2種形式的reduce:

如果流為空,則會返回幺元值,你就再也不需要處理Optional類了。
現在,假設你有一個對象流,并且想要對某些屬性求和,例如字符串流中的所有字符串的長度,那么你就不能使用簡單形式的reduce,而是需要(T,T)->T這樣的函數,即引元和結果的類型相同的函數。但是在這種情況下,你有兩種類型:流的元素具有String類型,而累積結果是整數。有一種形式的reduce可以處理這種情況。
首先,你需要提供一種“累積器”函數(total,word)->total+word.length()。這個函數會被反復調用,產生累積的總和。但是,當計算被并行化時,會有多個這種類型的計算,你需要將它們的結果合并。因此,你需要提供第二個函數來執行此處理。完整的調用如下:

注意:在實踐中,你可能并不會頻繁地用到reduce方法。通常,映射為數字流并使用其方法來計算總和、最大值和最小值會更容易。(我們將在1.13節中討論數字流。)在這個特定示例中,你可以調用words.mapToInt(String::length).sum(),因為它不涉及裝箱操作,所以更簡單也更高效。
注意:有時reduce會顯得并不夠通用。例如,假設我們想要收集BitSet中的結果。如果收集操作是并行的,那么就不能直接將元素放到單個BitSet中,因為BitSet對象不是線程安全的。因此,我們不能使用reduce,因為每個部分都需要以其自己的空集開始,并且reduce只能讓我們提供一個幺元值。此時,應該使用collect,它會接受單個引元:
1.一個提供者,它會創建目標類型的新實例,例如散列集的構造器。
2.一個累積器,它會將一個元素添加到一個實例上,例如add方法。
3.一個組合器,它會將兩個實例合并成一個,例如addAll。
下面的代碼展示了collect方法是如何操作位集的:

java.util.Stream 8
·Optional<T>reduce(BinaryOperator<T>accumulator)
·T reduce(T identity,BinaryOperator<T>accumulator)
·<U>U reduce(U identity,BiFunction<U,?super T,U>accumulator,BinaryOperator<U>combiner)
用給定的accumulator函數產生流中元素的累積總和。如果提供了幺元,那么第一個被累計的元素就是該幺元。如果提供了組合器,那么它可以用來將分別累積的各個部分整合成總和。
·<R>Rcollect(Supplier<R>supplier,BiConsumer<R,?superT>
將元素收集到類型R的結果中。在每個部分上,都會調用supplier來提供初始結果,調用accumulator來交替地將元素添加到結果中,并調用combiner來整合兩個結果。
- 機器學習系統:設計和實現
- 編程卓越之道(卷3):軟件工程化
- HoloLens Beginner's Guide
- 編寫高質量代碼:改善Python程序的91個建議
- Magento 1.8 Development Cookbook
- Python數據可視化之Matplotlib與Pyecharts實戰
- D3.js 4.x Data Visualization(Third Edition)
- Visual C#通用范例開發金典
- Instant Lucene.NET
- 好好學Java:從零基礎到項目實戰
- Scratch趣味編程:陪孩子像搭積木一樣學編程
- Access 2010數據庫應用技術實驗指導與習題選解(第2版)
- Learning JavaScript Data Structures and Algorithms(Second Edition)
- Arduino可穿戴設備開發
- SwiftUI極簡開發