摘要:多級(jí)分組的為鍵,類(lèi)型所對(duì)應(yīng)的集合為值一級(jí)分類(lèi)為的,二級(jí)分類(lèi)為的按子集收集數(shù)據(jù)的為鍵,類(lèi)型所對(duì)應(yīng)的集合的為值分區(qū)分區(qū)是分組的特殊情況由一個(gè)謂詞返回一個(gè)布爾值的函數(shù)作為分類(lèi)函數(shù),它稱(chēng)分區(qū)函數(shù)。
歸約和匯總 查找流中的最大值和最小值收集器可以簡(jiǎn)潔而靈活地定義collect用來(lái)生成結(jié)果集合的標(biāo)準(zhǔn)。更具體地說(shuō),對(duì)流調(diào)用 collect 方法將對(duì)流中的元素觸發(fā)一個(gè)歸約操作(由Collector來(lái)參數(shù)化)。一般來(lái)說(shuō),Collector 會(huì)對(duì)元素應(yīng)用一個(gè)轉(zhuǎn)換函數(shù)(很多時(shí)候是不體現(xiàn)任何效果的恒等轉(zhuǎn)換, 例如 toList ),并將結(jié)果累積在一個(gè)數(shù)據(jù)結(jié)構(gòu)中,從而產(chǎn)生這一過(guò)程的最終輸出。下面就來(lái)學(xué)習(xí)那些可以從Collectors 類(lèi)提供的工廠方法(例如groupingBy)創(chuàng)建的收集器。
Collectors.maxBy 和 Collectors.minBy 來(lái)計(jì)算流中的最大或最小值。
Optional匯總maxDish = Dish.menu.stream(). collect(Collectors.maxBy(Comparator.comparing(Dish::getCalories))); maxDish.ifPresent(System.out::println); Optional minDish = Dish.menu.stream(). collect(Collectors.minBy(Comparator.comparing(Dish::getCalories))); minDish.ifPresent(System.out::println);
Collectors.summingInt 匯總求和;
Collectors.averagingInt 匯總求平均值;
Collectors.summarizingInt 匯總所有信息包括數(shù)量、求和、平均值、最小值、最大值;
//求總熱量 int totalColories = Dish.menu.stream().collect(Collectors.summingInt(Dish::getCalories)); System.out.println(totalColories); //求平均熱量 double averageColories = Dish.menu.stream().collect(Collectors.averagingInt(Dish::getCalories)); System.out.println(averageColories); //匯總 IntSummaryStatistics menuStatistics = Dish.menu.stream().collect(Collectors.summarizingInt(Dish::getCalories)); System.out.println(menuStatistics); IntSummaryStatistics{count=9, sum=4300, min=120, average=477.777778, max=800}連接字符串
joining 工廠方法返回的收集器會(huì)把對(duì)流中每一個(gè)對(duì)象應(yīng)用toString方法得到的所有字符串連接成一個(gè)字符串。
String menu = Dish.menu.stream().map(Dish::getName).collect(Collectors.joining(",")); System.out.println(menu); //pork,beef,chicken,french fries,rice,season fruit,pizza,prawns,salmonCollectors.reducing
Collectors.reducing 工廠方法是上面所有工廠方法的一般情況,它完全可以實(shí)現(xiàn)上述方法的功能。它需要三個(gè)參數(shù):
第一個(gè)參數(shù)是歸約操作的起始值,也是流中沒(méi)有元素時(shí)的返回值,所以很顯然對(duì)于數(shù)值和而言0是一個(gè)合適的值。
第二個(gè)參數(shù)是一個(gè) Function,就是具體的取值函數(shù)。
第三個(gè)參數(shù)是一個(gè) BinaryOperator,將兩個(gè)項(xiàng)目累積成一個(gè)同類(lèi)型的值。。
int totalCalories = Dish.menu.stream().collect(Collectors.reducing( 0, Dish::getCalories, (i, j) -> i + j));分組
用Collectors.groupingBy工廠方法返回的收集器可以實(shí)現(xiàn)分組任務(wù),分組操作的結(jié)果是一個(gè)Map,把分組函數(shù)返回的值作為映射的鍵,把流中 所有具有這個(gè)分類(lèi)值的項(xiàng)目的列表作為對(duì)應(yīng)的映射值。
多級(jí)分組//Dish的Type為鍵,Dish類(lèi)型所對(duì)應(yīng)的dish集合為值 Map按子集收集數(shù)據(jù)> dishesByType = Dish.menu.stream().collect(Collectors.groupingBy(Dish::getType)); System.out.println(dishesByType); //{FISH=[prawns, salmon], OTHER=[french fries, rice, season fruit, pizza], MEAT=[pork, beef, chicken]} //一級(jí)分類(lèi)為Dish的Type,二級(jí)分類(lèi)為Dish的CaloricLevel Map >> dishes = Dish.menu.stream() .collect(Collectors.groupingBy(Dish::getType, Collectors.groupingBy(Dish::getLevel))); System.out.println(dishes); //{FISH={NORMAL=[salmon], DIET=[prawns]}, OTHER={NORMAL=[french fries, pizza], DIET=[rice, season fruit]}, MEAT={NORMAL=[beef], FAT=[pork], DIET=[chicken]}}
//Dish的Type為鍵,Dish類(lèi)型所對(duì)應(yīng)的dish集合的size為值 Map分區(qū)dishTypeCount = Dish.menu.stream().collect(Collectors.groupingBy(Dish::getType, Collectors.counting())); System.out.println(dishTypeCount); //{FISH=2, OTHER=4, MEAT=3}
分區(qū)是分組的特殊情況:由一個(gè)謂詞(返回一個(gè)布爾值的函數(shù))作為分類(lèi)函數(shù),它稱(chēng)分區(qū)函數(shù)。分區(qū)函數(shù)返回一個(gè)布爾值,這意味著得到的分組 Map 的鍵類(lèi)型是 Boolean,于是它最多可以分為兩組——true是一組,false是一組。分區(qū)的好處在于保留了分區(qū)函數(shù)返回true或false的兩套流元素列表。
Map小結(jié)>> partitioningDish = Dish.menu.stream().collect(Collectors.partitioningBy(Dish::isVegetarian, Collectors.groupingBy(Dish::getType))); System.out.println(partitioningDish); //false={FISH=[prawns, salmon], MEAT=[pork, beef, chicken]}, //true={OTHER=[french fries, rice, season fruit, pizza]}
下表展示 Collectors 類(lèi)的靜態(tài)工廠方法。
工廠方法 | 返回類(lèi)型 | 作用 |
---|---|---|
toList | List |
把流中所有項(xiàng)目收集到一個(gè) List |
toSet | Set |
把流中所有項(xiàng)目收集到一個(gè) Set,刪除重復(fù)項(xiàng) |
toCollection | Collection |
把流中所有項(xiàng)目收集到給定的供應(yīng)源創(chuàng)建的集合menuStream.collect(toCollection(), ArrayList::new) |
counting | Long | 計(jì)算流中元素的個(gè)數(shù) |
sumInt | Integer | 對(duì)流中項(xiàng)目的一個(gè)整數(shù)屬性求和 |
averagingInt | Double | 計(jì)算流中項(xiàng)目 Integer 屬性的平均值 |
summarizingInt | IntSummaryStatistics | 收集關(guān)于流中項(xiàng)目 Integer 屬性的統(tǒng)計(jì)值,例如最大、最小、 總和與平均值 |
joining | String | 連接對(duì)流中每個(gè)項(xiàng)目調(diào)用 toString 方法所生成的字符串collect(joining(", ")) |
maxBy | Optional |
一個(gè)包裹了流中按照給定比較器選出的最大元素的 Optional, 或如果流為空則為 Optional.empty() |
minBy | Optional |
一個(gè)包裹了流中按照給定比較器選出的最小元素的 Optional, 或如果流為空則為 Optional.empty() |
reducing | 歸約操作產(chǎn)生的類(lèi)型 | 從一個(gè)作為累加器的初始值開(kāi)始,利用 BinaryOperator 與流 中的元素逐個(gè)結(jié)合,從而將流歸約為單個(gè)值累加int totalCalories = menuStream.collect(reducing(0, Dish::getCalories, Integer::sum)); |
collectingAndThen | 轉(zhuǎn)換函數(shù)返回的類(lèi)型 | 包裹另一個(gè)收集器,對(duì)其結(jié)果應(yīng)用轉(zhuǎn)換函數(shù)int howManyDishes = menuStream.collect(collectingAndThen(toList(), List::size)) |
groupingBy | Map |
根據(jù)項(xiàng)目的一個(gè)屬性的值對(duì)流中的項(xiàng)目作問(wèn)組,并將屬性值作 為結(jié)果 Map 的鍵 |
partitioningBy | Map |
根據(jù)對(duì)流中每個(gè)項(xiàng)目應(yīng)用謂詞的結(jié)果來(lái)對(duì)項(xiàng)目進(jìn)行分區(qū) |
package com.company.bean; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; /** * Created by liuguoquan on 2017/4/26. */ public class Dish { private String name; private boolean vegetarian; private int calories; private Type type; private CaloricLevel level; public CaloricLevel getLevel() { if (calories <= 400) { return CaloricLevel.DIET; } else if (calories <= 700) { return CaloricLevel.NORMAL; } return CaloricLevel.FAT; } public void setLevel(CaloricLevel level) { this.level = level; } public enum Type { MEAT, FISH, OTHER } public enum CaloricLevel { DIET, NORMAL, FAT } public Dish(String name, boolean vegetarian, int calories, Type type) { this.name = name; this.vegetarian = vegetarian; this.calories = calories; this.type = type; } public String getName() { return name; } public boolean isVegetarian() { return vegetarian; } public int getCalories() { return calories; } public Type getType() { return type; } @Override public String toString() { return name; } public static final Listmenu = Arrays.asList( new Dish("pork", false, 800, Dish.Type.MEAT), new Dish("beef", false, 700, Dish.Type.MEAT), new Dish("chicken", false, 400, Dish.Type.MEAT), new Dish("french fries", true, 530, Dish.Type.OTHER), new Dish("rice", true, 350, Dish.Type.OTHER), new Dish("season fruit", true, 120, Dish.Type.OTHER), new Dish("pizza", true, 550, Dish.Type.OTHER), new Dish("prawns", false, 400, Dish.Type.FISH), new Dish("salmon", false, 450, Dish.Type.FISH)); }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/69990.html
摘要:大家好,我是樂(lè)字節(jié)的小樂(lè)。需要注意的是很多流操作本身就會(huì)返回一個(gè)流,所以多個(gè)操作可以直接連接起來(lái),如下圖這樣,操作可以進(jìn)行鏈?zhǔn)秸{(diào)用,并且并行流還可以實(shí)現(xiàn)數(shù)據(jù)流并行處理操作。為集合創(chuàng)建并行流。 大家好,我是樂(lè)字節(jié)的小樂(lè)。說(shuō)起流,我們會(huì)聯(lián)想到手機(jī)、電腦組裝流水線(xiàn),物流倉(cāng)庫(kù)商品包裝流水線(xiàn)等等,如果把手機(jī) ,電腦,包裹看做最終結(jié)果的話(huà),那么加工商品前的各種零部件就可以看做數(shù)據(jù)源,而中間一系列的...
摘要:歸約操作計(jì)算有效訂單總金額有效訂單總金額收集數(shù)據(jù)收集將流轉(zhuǎn)換為其他形式,方法作為終端操作,接收一個(gè)接口的實(shí)現(xiàn),用于給中元素做匯總的方法。 接上一篇:《Java8新特性之stream》,下面繼續(xù)接著講Stream 5、流的中間操作 常見(jiàn)的流的中間操作,歸為以下三大類(lèi):篩選和切片流操作、元素映射操作、元素排序操作:showImg(https://segmentfault.com/img/b...
摘要:使用解決的數(shù)據(jù)流問(wèn)題原文譯者飛龍協(xié)議在年三月發(fā)布,距離現(xiàn)在年三月五號(hào)快有一年了。除了,最實(shí)用的特性是新的數(shù)據(jù)流。是吧,注是瀏覽器上的數(shù)據(jù)流的接口,并解決了上述問(wèn)題。 使用Intellij IDEA 解決Java8的數(shù)據(jù)流問(wèn)題 原文:Fixing Java 8 Stream Gotchas with IntelliJ IDEA 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 ...
摘要:表達(dá)式體現(xiàn)了函數(shù)式編程的思想,即一個(gè)函數(shù)亦可以作為另一個(gè)函數(shù)參數(shù)和返回值,使用了函數(shù)作參數(shù)返回值的函數(shù)被稱(chēng)為高階函數(shù)。對(duì)流對(duì)象進(jìn)行及早求值,返回值不在是一個(gè)對(duì)象。 Java8主要的改變是為集合框架增加了流的概念,提高了集合的抽象層次。相比于舊有框架直接操作數(shù)據(jù)的內(nèi)部處理方式,流+高階函數(shù)的外部處理方式對(duì)數(shù)據(jù)封裝更好。同時(shí)流的概念使得對(duì)并發(fā)編程支持更強(qiáng)。 在語(yǔ)法上Java8提供了Lamb...
摘要:數(shù)據(jù)流教程原文譯者飛龍協(xié)議這個(gè)示例驅(qū)動(dòng)的教程是數(shù)據(jù)流的深入總結(jié)。但是的數(shù)據(jù)流是完全不同的東西。數(shù)據(jù)流是單體,并且在函數(shù)式編程中起到重要作用。列表上的所有流式操作請(qǐng)見(jiàn)數(shù)據(jù)流的?;镜臄?shù)據(jù)流使用特殊的表達(dá)式,例如,而不是,而不是。 Java 8 數(shù)據(jù)流教程 原文:Java 8 Stream Tutorial 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 這個(gè)示例驅(qū)動(dòng)的教程是J...
閱讀 1738·2021-10-29 13:11
閱讀 965·2021-09-22 10:02
閱讀 1749·2021-08-20 09:35
閱讀 1623·2019-08-30 15:54
閱讀 2572·2019-08-30 15:44
閱讀 1451·2019-08-29 16:52
閱讀 1169·2019-08-23 12:56
閱讀 817·2019-08-22 15:16