Java 8 - 收集器Collectors
文章目錄
- Pre
- 簡介
- 收集器用作高級歸約
- 預定義收集器
Pre
我們前面學到了,流可以用類似于數據庫的操作幫助你處理集合。
它們支持兩種類型的操作:
-
中間操作(如 filter 或 map )
-
終端操作(如 count 、 findFirst 、 forEach 和 reduce )
中間操作可以鏈接起來,將一個流轉換為另一個流。這些操作不會消耗流,其目的是建立一個流水線。
與此相反,終端操作會消耗流,以產生一個最終結果,例如返回流中的最大元素。它們通常可以通過優化流水線來縮短計算時間。
前面使用過了collect 終端操作了,當時主要是用來把 Stream 中所有的元素結合成一個 List 。
我們學習完收集器以后,會知道collect 是一個歸約操作,就像 reduce 一樣可以接受各種做法作為參數,將流中的元素累積成一個匯總結果。具體的做法是通過定義新的Collector 接口來定義的,因此區分 Collection 、 Collector 和 collect 是很重要的。
舉幾個例子,先感受下
- 對一個交易列表按貨幣分組,獲得該貨幣的所有交易額總和(返回一個 Map<Currency,Integer> )
- 將交易列表分成兩組:貴的和不貴的(返回一個 Map<Boolean, List<Transaction>> )
- 創建多級分組,比如按城市對交易分組,然后進一步按照貴的和不貴的分組(返回一個Map<Boolean, List<Transaction>> )。
我們來看下不是用流,是如何處理的
如果用流呢?
簡介
Map<Currency, List<Transaction>> transactionsByCurrencies =transactions.stream().collect(groupingBy(Transaction::getCurrency));這個例子清晰的展示了函數式編程相對于指令式編程的一個主要優勢:只需指出希望的結果—“做什么”,而不用操心執行的步驟——“如何做” 。
這個例子中傳遞給 collect方法的參數是 Collector 接口的一個實現,也就是給 Stream 中元素做匯總的方法。 我們之前接觸的toList 只是說“按順序給每個元素生成一個列表”; groupingBy 說的是“生成一個Map ,它的鍵是(貨幣)桶,值則是桶中那些元素的列表”。
要是做多級分組,指令式和函數式之間的區別就會更加明顯:由于需要好多層嵌套循環和條件,指令式代碼很快就變得更難閱讀、更難維護、更難修改。相比之下,函數式版本只要再加上一個收集器就可以輕松地增強功能了。
收集器用作高級歸約
對流調用collect 方法將對流中的元素觸發一個歸約操作(由 Collector 來參數化)。
看個歸約操作的示例: 遍歷流中的每個元素,并讓 Collector 進行處理
一般來說, Collector 會對元素應用一個轉換函數(很多時候是不體現任何效果的恒等轉換例如 toList ),并將結果累積在一個數據結構中,從而產生這一過程的最終輸出。
例如,
Map<Currency, List<Transaction>> transactionsByCurrencies =transactions.stream().collect(groupingBy(Transaction::getCurrency));這個交易分組的例子中,轉換函數提取了每筆交易的貨幣,隨后使用貨幣作為鍵,將交易本身累積在生成的 Map 中。
Collector 接口中方法的實現決定了如何對流執行歸約操作。但 Collectors 實用類提供了很多靜態工廠方法,可以方便地創建常見收集器的實例,只要拿來用就可以了。最直接和最常用的收集器是 toList靜態方法,它會把流中所有的元素收集到一個 List 中:
List<Transaction> transactions = transactionStream.collect(Collectors.toList());預定義收集器
預定義收集器的功能,也就是那些可以從 Collectors類提供的工廠方法(例如 groupingBy )創建的收集器。
它們主要提供了三大功能:
- 將流元素歸約和匯總為一個值
- 元素分組
- 元素分區
后續的博文我們繼續對這幾類展開學習~
總結
以上是生活随笔為你收集整理的Java 8 - 收集器Collectors的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL - mysqldump多种方
- 下一篇: Java 8 - 收集器Collecto