Java 8 Streams API:對Stream分組和分割槽
這篇文章展示瞭如何使用 Streams API 中的 Collector 及 groupingBy 和 partitioningBy 來對流中的元素進行分組和分割槽。
思考一下 Employee 物件流,每個物件對應一個名字、城市和銷售數量,如下表所示:
+----------+------------+-----------------+ | Name | City | Number of Sales | +----------+------------+-----------------+ | Alice | London | 200 | | Bob | London | 150 | | Charles | New York | 160 | | Dorothy | Hong Kong | 190 | +----------+------------+-----------------+
分組
首先,我們利用(lambda表示式出現之前的)命令式風格Java 程式對流中的僱員按城市進行分組:
Map<String, List<Employee>> result = new HashMap<>(); for (Employee e : employees) { String city = e.getCity(); List<Employee> empsInCity = result.get(city); if (empsInCity == null) { empsInCity = new ArrayList<>(); result.put(city, empsInCity); } empsInCity.add(e); }
你可能很熟悉寫這樣的程式碼,你也看到了,一個如此簡單的任務就需要這麼多程式碼!
而在 Java 8 中,你可以使用 groupingBy 收集器,一條語句就能完成相同的功能,像這樣:
Map<String, List<Employee>> employeesByCity = employees.stream().collect(groupingBy(Employee::getCity));
結果如下面的 map 所示:
{New York=[Charles], Hong Kong=[Dorothy], London=[Alice, Bob]}
還可以計算每個城市中僱員的數量,只需傳遞一個計數收集器給 groupingBy 收集器。第二個收集器的作用是在流分類的同一個組中對每個元素進行遞迴操作。
Map<String, Long> numEmployeesByCity = employees.stream().collect(groupingBy(Employee::getCity, counting()));
結果如下面的 map 所示:
{New York=1, Hong Kong=1, London=2}
順便提一下,該功能與下面的 SQL 語句是等同的:
select city, count(*) from Employee group by city
另一個例子是計算每個城市的平均年齡,這可以聯合使用 averagingInt 和 groupingBy 收集器:
Map<String, Double> avgSalesByCity = employees.stream().collect(groupingBy(Employee::getCity, averagingInt(Employee::getNumSales)));
結果如下 map 所示:
{New York=160.0, Hong Kong=190.0, London=175.0}
分割槽
分割槽是一種特殊的分組,結果 map 至少包含兩個不同的分組——一個true,一個false。例如,如果想找出最優秀的員工,你可以將所有僱員分為兩組,一組銷售量大於 N,另一組小於 N,使用 partitioningBy 收集器:
Map<Boolean, List<Employee>> partitioned = employees.stream().collect(partitioningBy(e -> e.getNumSales() > 150));
輸出如下結果:
{false=[Bob], true=[Alice, Charles, Dorothy]}
你也可以將 groupingBy 收集器傳遞給 partitioningBy 收集器來將聯合使用分割槽和分組。例如,你可以統計每個分割槽中的每個城市的僱員人數:
Map<Boolean, Map<String, Long>> result = employees.stream().collect(partitioningBy(e -> e.getNumSales() > 150, groupingBy(Employee::getCity, counting())));
這樣會生成一個二級 Map:
{false={London=1}, true={New York=1, Hong Kong=1, London=1}}
相關文章
- Java8-10-Stream分組與分割槽詳解Java
- Java8中的 lambda 和Stream APIJavaAPI
- Java8的Stream API使用JavaAPI
- Java8新特性--Stream APIJavaAPI
- Java8 Stream常用API整理JavaAPI
- Java8中的Stream APIJavaAPI
- Java 8新特性(二):Stream APIJavaAPI
- java8 Stream APi 入門JavaAPI
- Java8 Lambda表示式與Stream API (二): Stream API的使用JavaAPI
- Java8 - Stream API快速入門JavaAPI
- Java 8 Stream Api 中的 peek 操作JavaAPI
- 全面學習分割槽表及分割槽索引(8)--增加和收縮表分割槽索引
- 模仿Java Stream API 運算元組/切片JavaAPI
- mysql的分割槽和分表MySql
- Java 8 Stream API 轉換到 Kotlin 集合APIJavaAPIKotlin
- MySql分表、分庫、分片和分割槽MySql
- Java 8 Streams filterJavaFilter
- Java 8 Streams map()Java
- 範圍分割槽表和INTERVAL分割槽表對於SPLIT分割槽的區別
- Java 8中的Stream API使用指南JavaAPI
- Win8劃分硬碟分割槽的技巧硬碟
- Apache Spark:分割槽和分桶 - NiveditaApacheSpark
- 使用split對分割槽表再分割槽
- Java8新特性第3章(Stream API)JavaAPI
- Win8劃分硬碟分割槽有訣竅硬碟
- PostgreSQL和oracle表分割槽對比SQLOracle
- Java 8 StreamJava
- mysql表水平拆分和分割槽分表MySql
- hive分割槽和分桶你熟悉嗎?Hive
- mysql 分表 分割槽MySql
- Java 8新特性之旅:使用Stream API處理集合JavaAPI
- win10硬碟分割槽怎麼分_win10系統如何對硬碟分割槽Win10硬碟
- Oracle分割槽表基礎運維-05組合分割槽Oracle運維
- Oracle Stream(2)--Streams功能Oracle
- Oracle Stream(1)--Streams概述Oracle
- 全面學習分割槽表及分割槽索引(6)--建立range-list組合分割槽索引
- DM7,DM8和ORACLE中對分割槽split的區別Oracle
- oracle分割槽表和分割槽表exchangeOracle