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