用流收集数据Collectors的用法介绍分组groupingBy、分区partitioningBy(一)
文章目錄
- 一、收集器簡介
- 二、歸約和匯總
- 1、查找流中最大值和最小值Collectors.maxBy和,Collectors.minBy
- 2、匯總
- 3、連接字符串
- 4、廣義歸約匯總
- 三、分組
- 1、多級分組
- 2、按子組收集數據
- 3、將收集器結果轉換為另一種類型
- 4、分區partitioningBy
這一張我們主要講用流來收集數據,函數式的編程相對于指令式編程的一個優勢:你只需指出希望的結果做什么,而不用操心執行的步驟怎么做。
這一節所講的方法都是基于收集collect里面參數Collectors里面的靜態方法靜態方法。
小插曲:import static java.util.stream.Collectors.*;可以把所有靜態方法引入
一、收集器簡介
收集器非常有用,因為它可以簡潔而又靈活地定義collect用來生成結果集合的標準。更具體說,對流調用collect方法將對流中的元素發一個歸約操作。
本章剩下部分,主要探討預定義收集器功能,也就是那些可以從Collector類提供的工廠方法創建收集器。主要提供三大功能:
- 將流元素歸約和匯總一個值
- 元素分組
- 元素分區
二、歸約和匯總
利用counting
public static void testCounting() {Long collect = menu.stream().collect(counting());}1、查找流中最大值和最小值Collectors.maxBy和,Collectors.minBy
maxBy參數接受一個Compartor比較結果。例:
public static void testMaxby() {Comparator<Dish> dishComparator = Comparator.comparingInt(Dish::getCalories);Optional<Dish> collect = menu.stream().collect(maxBy(dishComparator));}2、匯總
Collectors類專門為匯總提供了一個工廠方法:Collectors.summingInt。接受一個對象映射為求和所需int函數。例:
public static void testSummingInt() {Integer collect = menu.stream().collect(summingInt(Dish::getCalories));System.out.println(collect);}Collectors.summingLong和Collectors.summingDouble方法用法完全一樣可以用于求和long和double,求平球輸方法averagingLong、averagingDouble、averagingInt。
summarizingInt、summarizingLong、summarizingDouble方法可以數出元素個數、平均數、總和、最大值和最小值。例:
3、連接字符串
joining工廠方法返回的收集器會把中每一個對象應用toString()方法得到的所有字符串
連接成一個字符串。例:把所有的菜肴名稱連接起來
重載方法可以添加用什么分隔符
public static void testJoining() {String collect = menu.stream().map(Dish::getName).collect(joining(","));System.out.println(collect);}4、廣義歸約匯總
前面已經討論過的收集器,可以用一個reduing工廠方法定義歸約過程的特殊情況。例:
public static void testCollectReduing() {Integer collect = menu.stream().collect(reducing(0, Dish::getCalories, (i, j) -> i + j));}它需要三個參數:
第一個參數:歸約起始位置
第二個參數:轉換成表示所函熱量的int
第三個參數:是一個BInaryOperator,將兩個項目累計為同一個值。例如對int求和。
三、分組
java8分組類似于常見數據庫分組,我們java8提供了Collectors.groupingBy工廠方法返回的收集器就可以輕松的完成分組。例:
按照菜單類型分組
1、多級分組
實現多級分組,可以使用一個由雙參數版本的Collectors.groupingBy工廠方法創建收集器,除了普通的分類函數外,還可以接受collector類型的第二個參數。進行二級分組可以把內層的groupingby傳遞給外層。
例:
n級分組就會得到一個n級樹形結構的n級Map
2、按子組收集數據
傳遞給第一個groupingBy的第二個收集器可以是任何類型,而不一定是一個groupingBy。例:
Map<Dish.Type, Long> typesCount = menu.stream().collect( groupingBy(Dish::getType, counting()));注意:普通單參數groupingBy單參數其實就是groupbingBy(f,toList)的簡寫
在舉一個例子加深印象
Map<Type, Optional<Dish>> collect1 = menu.stream().collect(groupingBy(Dish::getType,maxBy(Comparator.comparingInt(Dish::getCalories))));3、將收集器結果轉換為另一種類型
收集器轉換成另一種類型可以用:Collectors.collectingAndThen
例:
collectingAndThen工廠發方法接受兩個參數:1、轉換收集器(Collector);2、轉換函數(Function)。返回值是另一個收集器。
4、分區partitioningBy
分區的好處在于保留分區函數返回true或false的兩套流元素列表。partitioningBy工廠方法有一個重載方法,第二個參數可以傳遞收集器。
public static void testPartitioningBy() {Map<Boolean, Map<Type, List<Dish>>> collect = menu.stream().collect(partitioningBy(Dish::isVegetarian, groupingBy(Dish::getType)));}總結:Collectors類的靜態工廠方法
總結
以上是生活随笔為你收集整理的用流收集数据Collectors的用法介绍分组groupingBy、分区partitioningBy(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JAVA8 Stream方法使用详解re
- 下一篇: 并行数据处理与性能详解与ForkJoin