Java12 Collectors.teeing 你真的需要了解一下

前言

在 Java 12 裡面有個非常好用但在官方 JEP 沒有公佈的功能,因為它只是 Collector 中的一個小改動,它的作用是 merge 兩個 collector 的結果,這句話顯得很抽象,老規矩,我們先來看個圖:

更好閱讀體驗請訪問:https://dayarch.top/p/jdk12-collectors-teeing-api-usage.html

Java12 Collectors.teeing 你真的需要了解一下

管道改造經常會用這個小東西,通常我們叫它「三通」,它的主要作用就是將 downstream1 和 downstream2 的流入合併,然後從 merger 流出

有了這個形象的說明我們就進入正題吧

Collectors.teeing

上面提到的小功能就是 Collectors.teeing API, 先來看一下 JDK 關於該 API 的說明,看著覺得難受的直接忽略,繼續向下看例子就好了:

API 描述重的一句話非常關鍵:

Every element passed to the resulting collector is processed by both downstream collectors

結合「三通圖」來說明就是,集合中每一個要被傳入 merger 的元素都會經過 downstream1 和 downstream2 的加工處理

其中 merger 類型是 BiFunction,也就是說接收兩個參數,並輸出一個值,請看它的 apply 方法

至於可以如何處理,我們來看一些例子吧

例子

為了更好的說明 teeing 的使用,列舉了四個例子,看過這四個例子再回看上面的 API 說明,相信你會柳暗花明了

計數和累加

先來看一個經典的問題,給定的數字集合,需要映射整數流中的元素數量和它們的和

通過 Collectors.teeing 處理

  • downstream1 通過 Collectors 的靜態方法 counting 進行集合計數
  • downstream2 通過 Collectors 的靜態方法 summingInt 進行集合元素值的累加
  • merger 通過 CountSum 構造器收集結果

運行結果:

CountSum{count=7, sum=46}

我們通過 teeing 一次性得到我們想要的結果,繼續向下看其他例子:

最大值與最小值

通過給定的集合, 一次性計算出集合的最大值與最小值,同樣新建一個類 MinMax,並創建構造器用於 merger 收集結果

通過 teeing API 計算結果:

  • downstream1 通過 Collectors 的靜態方法 minBy,通過 Comparator 比較器按照自然排序找到最小值
  • downstream2 通過 Collectors 的靜態方法 maxBy,通過 Comparator 比較器按照自然排序找到最大值
  • merger 通過 MinMax 構造器收集結果,只不過為了應對 NPE,將 BiFunction 的兩個入參經過 Optional 處理

運行結果:

MinMax{min=1, max=12}

為了驗證一下 Optional,我們將集合中添加一個 null 元素,並修改一下排序規則來看一下排序結果:

  • downstream1 處理規則是將 null 放在排序的最前面
  • downstream2 處理規則是將 null 放在排序的最後面
  • merger 處理時,都會執行 optional.orElse 方法,分別輸出最小值與最大值

運行結果:

MinMax{min=-2147483648, max=2147483647}

瓜的總重和單個重量

接下來舉一個更貼合實際的操作對象的例子

通過 teeing API 計算總重量和單個列表重量

  • downstream1 通過 Collectors 的靜態方法 summingInt 做重量累加
  • downstream2 通過 Collectors 的靜態方法 mapping 提取出瓜的重量,並通過流的終結操作 toList() 獲取結果
  • merger 通過 WeightsAndTotal 構造器獲取結果

運行結果:

WeightsAndTotal{totalWeight=19500, weights=[1200, 3000, 2600, 1600, 1200, 2600, 1700, 3000, 2600]}

繼續一個更貼合實際的例子吧:

預約人員列表和預約人數

通過 teeing API 處理

  • downstream1 通過 filtering 方法過濾出確定參加的人,並 mapping 出他們的姓名,最終放到 toList 集合中
  • downstream2 通過 summingInt 方法計數累加
  • merger 通過 EventParticipation 構造器收集結果

其中我們定義了 var result 來收集結果,並沒有指定類型,這個語法糖也加速了我們編程的效率

運行結果:

EventParticipation { guests = [Marco, Roger], total number of participants = 11 }

總結

其實 teeing API 就是靈活應用 Collectors 裡面定義的靜態方法,將集合元素通過 downstream1 和 downstream2 進行處理,最終通過 merger 收集起來,當項目中有同時獲取兩個收集結果時,是時候應用我們的 teeing API 了

靈魂追問

  1. Collectors 裡面的靜態方法你應用的熟練嗎?
  2. 項目中你們在用 JDK 的版本是多少?
  3. Lambda 的使用熟練嗎?
  4. 你的燈還亮著嗎?
Java12 Collectors.teeing 你真的需要了解一下

  1. https://dayarch.top/categories/Coding/Java-Concurrency/
  2. https://dayarch.top/p/maven-dependency-optional-transitive.html
  3. https://dayarch.top/p/easyexcel-read.html
  4. https://dayarch.top/p/java-string-interview.html

趣味原創解析Java技術棧問題,將複雜問題簡單化,將抽象問題圖形化落地

如果對我的專題內容感興趣,或搶先看更多內容,歡迎訪問我的博客 https://dayarch.top


分享到:


相關文章: