欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java 流的高級使用之收集數(shù)據(jù)解析

 更新時間:2021年08月25日 09:49:57   作者:FXBStudy  
這篇文章主要介紹了Java 流的高級使用之收集數(shù)據(jù)解析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

一、前言

1.1 收集器

收集器的接口是java.util.stream.Collector,我們只需要調(diào)用流的collect方法并傳遞給一個Collector接口的一個實現(xiàn)(也就是給Stream中元素做匯總的方法),就可以了。例如java.util.stream.Collectors類的toList()方法,該方法就會返回一個按順序給每個元素生成一個列表的Collector接口的實現(xiàn)。

收集器非常有用,因為它可以簡介而靈活地定義collect用來生成結(jié)果集合的標(biāo)準(zhǔn)。更具體地說,對流調(diào)用collect方法將對流中的元素觸發(fā)一個規(guī)約操作(由Collector來參數(shù)化)。

1.2 預(yù)定義收集器

JDK為我們提供了java.util.stream.Collectors類,其為我們提供了很多靜態(tài)工廠方法,可以方便地創(chuàng)建常見的收集器實例,而我們只要拿來用就可以了。最直接和最常用的收集器是toList靜態(tài)方法,它會把流中所有的元素收集到一個List中。

Collectors類為我們提供的收集器,主要包含三大功能:

  • 將流元素規(guī)約和匯總為一個值
  • 元素分組
  • 元素分區(qū)

注意:因為其為我們提供的都是靜態(tài)方法,我們可以通過靜態(tài)導(dǎo)入的方式簡化代碼的書寫。

二、深入

2.1 規(guī)約和匯總

統(tǒng)計元素數(shù)量

Collectors為我們提供了counting方法,為我們提供了統(tǒng)計元素數(shù)量的收集器。實例:

long howManyDishes = menu.stream().collect(Collectors.counting());

上面的示例是利用預(yù)定義收集器實現(xiàn)的,其實Stream接口定義了count方法,因此我們也可以直接調(diào)用Stream提供的預(yù)定義方法來實現(xiàn),如下:

long howManyDishes = menu.stream().count();

功能一樣用哪個才好呢?其實如果你的需求只是統(tǒng)計流中元素的數(shù)量的時候,二者皆可。最大的區(qū)別在于count()是一個終端操作,而counting返回的是一個收集器,其可以和其它收集器聯(lián)合使用。

查找流中的最大值和最小值

Collectors為我們提供了maxBy方法和mixBy方法,為我們提供了計算流中的最大或最小值的收集器。實例:

Comparator<Dish> dishCaloriesComparator = Comparator.comparingInt(Dish::getCalories);
Optional<Dish> mostCalorieDish = menu.stream().collect(maxBy(dishCaloriesComparator));

匯總

求和

Collectors類專門為匯總提供了一個工廠方法: Collectors.summingInt。它可接受一個把對象映射為求和所需int的函數(shù),并返回一個收集器;該收集器在傳遞給普通的collect方法后即執(zhí)行我們需要的匯總操作。

類Collectors.summingLong和Collectors.summingDouble方法的作用完全一樣,可以用于求和字段為long或double的情況。

求出菜單列表的總熱量的示例:

int totalCalories = menu.stream().collect(summingInt(Dish::getCalories));

上面代碼的收集過程下圖所示。在遍歷流時,會把每一道菜都映射為其熱量,然后把這個數(shù)字累加到一個累加器(這里的初始值0)。

收集器的累加過程

平均值

Collectors類的averagingInt、averagingLong 和 averagingDouble 可以為我們生成計算數(shù)值的平均數(shù)的收集器:

double avgCalories = menu.stream().collect(averagingInt(Dish::getCalories));

綜合匯總

Collectors類為我們提供了summarizingInt工廠方法,其返回的收集器可以一次性統(tǒng)計出總數(shù)、總和、平均值、最大值和最小值。

例如,通過一次summarizing操作你可以就數(shù)出菜單中元素的個數(shù),并得到菜肴熱量總和、平均值、最大值和最小值:

IntSummaryStatistics menuStatistics =
        menu.stream().collect(summarizingInt(Dish::getCalories));

這個收集器會把所有這些信息收集到一個叫作IntSummaryStatistics的類里,它提供了方便的取值方法來訪問結(jié)果。打印menuStatisticobject會得到以下輸出:

IntSummaryStatistics{count=9, sum=4300, min=120, average=477.777778, max=800}

同樣,相應(yīng)的summarizingLong和summarizingDouble工廠方法有相關(guān)的LongSummaryStatistics 和DoubleSummaryStatistics 類 型 , 適用于收集的屬性是原始類型 long 或 double 的情況。

連接字符串

Collectors類為我們提供的joining工廠方法返回的收集器會把對流中每一個對象應(yīng)用toString方法得到的所有字符串連接成一個字符串。

這意味著你把菜單中所有菜肴的名稱連接起來,如下所示:

String shortMenu = menu.stream().map(Dish::getName).collect(joining());

注意: joining在內(nèi)部使用了StringBuilder來把生成的字符串逐個追加起來。

此外joining工廠方法有一個重載版本可以接受元素之間的分界符,這樣你就可以得到一個逗號分隔的菜肴名稱列表:

String shortMenu = menu.stream().map(Dish::getName).collect(joining(", "));

廣義的規(guī)約匯總

前面所提及的收集器都是一個可以用reducing工廠方法定義的規(guī)約過程的特殊情況而已。Collectors.reducing工廠方法是所有這些特殊情況的一般化。

public static <T,U> Collector<T,?,U> reducing(U identity,
                    Function<? super T,? extends U> mapper, BinaryOperator<U> op)

參數(shù)解析:

  • 第一個參數(shù)時規(guī)約操作的起始值,也是流中沒有元素時的返回值。
  • 第二個參數(shù)是Function,將做一定的轉(zhuǎn)換操作。
  • 第三個參數(shù)BinaryOperator,將兩個項目累積成一個同類型的值。

我們將上面的示例轉(zhuǎn)換一下:

Comparator<Dish> dishCaloriesComparator = Comparator.comparingInt(Dish::getCalories);
Optional<Dish> mostCalorieDish = menu.stream().collect(maxBy(dishCaloriesComparator));
// 轉(zhuǎn)換
Optional<Dish> mostCalorieDish = 
        menu.stream().collect(reducing(
                (d1,d2) -> d1.getCalories() > d1.getCalories() ? d1 : d2));

上面轉(zhuǎn)換示例中,我們使用的是一個單參數(shù)的reducing工廠方法創(chuàng)建的收集器,其可以看做是三個參數(shù)方法的特殊情況,它把流中的第一個項目作為起點,把恒等函數(shù)(即一個函數(shù)僅僅是返回其輸入?yún)?shù))作為一個轉(zhuǎn)換函數(shù)。

2.2 分組

一個常見的數(shù)據(jù)庫操作是根據(jù)一個或多個屬性對集合中的項目進(jìn)行分組。

假設(shè)你要把菜單中的菜按照類型進(jìn)行分類,有肉的放一組,有魚的放一組,其他的都放另一組。用Collectors.groupingBy工廠方法返回的收集器就可以輕松地完成這項任務(wù),如下所示:

Map<Dish.Type, List<Dish>> dishesByType =
        menu.stream().collect(groupingBy(Dish::getType));

這里,你給groupingBy方法傳遞了一個Function(以方法引用的形式),它提取了流中每一道Dish的Dish.Type。我們把這個Function叫作分類函數(shù),因為它用來把流中的元素分成不同的組。如下圖所示,分組操作的結(jié)果是一個Map,把分組函數(shù)返回的值作為映射的鍵,把流中所有具有這個分類值的項目的列表作為對應(yīng)的映射值。在菜單分類的例子中,鍵就是菜的類型,值就是包含所有對應(yīng)類型的菜肴的列表。

分組過程

特殊應(yīng)用示例:

public enum CaloricLevel{DIET,NORMAL,FAT}
Map<CaloricLevel, List<Dish>> dishesByCaloricLevel = menu.stream().collect(groupingBy(dish -> {
    if (dish.getCalories() <= 400)
        return CaloricLevel.DIET;
    else if (dish.getCalories() <= 700)
        return CaloricLevel.NORMAL;
    else
        return CaloricLevel.FAT;
}));

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解mybatis 批量更新數(shù)據(jù)兩種方法效率對比

    詳解mybatis 批量更新數(shù)據(jù)兩種方法效率對比

    這篇文章主要介紹了詳解mybatis 批量更新數(shù)據(jù)兩種方法效率對比,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • java數(shù)據(jù)結(jié)構(gòu)之搜索二叉樹

    java數(shù)據(jù)結(jié)構(gòu)之搜索二叉樹

    這篇文章主要為大家詳細(xì)介紹了java數(shù)據(jù)結(jié)構(gòu)之搜索二叉樹,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • 如何解決java中遇到的for input string:

    如何解決java中遇到的for input string: "" 報錯問題

    在本篇文章里小編給大家整理的是一篇關(guān)于如何解決java中遇到的(for input string: "")報錯內(nèi)容,需要的朋友們可以學(xué)習(xí)下。
    2020-02-02
  • Java 線程相關(guān)總結(jié)

    Java 線程相關(guān)總結(jié)

    這篇文章主要介紹了Java 線程的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-02-02
  • springboot+vue+elementsUI實現(xiàn)分角色注冊登錄界面功能

    springboot+vue+elementsUI實現(xiàn)分角色注冊登錄界面功能

    這篇文章主要給大家介紹了關(guān)于springboot+vue+elementsUI實現(xiàn)分角色注冊登錄界面功能的相關(guān)資料,Spring?Boot和Vue.js是兩個非常流行的開源框架,可以用來構(gòu)建Web應(yīng)用程序,需要的朋友可以參考下
    2023-07-07
  • Spring?Boot中自動執(zhí)行sql腳本的方法實例

    Spring?Boot中自動執(zhí)行sql腳本的方法實例

    在SpringBoot的架構(gòu)中,DataSourceInitializer類可以在項目啟動后初始化數(shù)據(jù),我們可以通過自動執(zhí)行自定義sql腳本初始化數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于Spring?Boot中自動執(zhí)行sql腳本的相關(guān)資料,需要的朋友可以參考下
    2022-01-01
  • java 數(shù)據(jù)類型有哪些取值范圍多少

    java 數(shù)據(jù)類型有哪些取值范圍多少

    這篇文章主要介紹了java 數(shù)據(jù)類型有哪些取值范圍多少的相關(guān)資料,網(wǎng)上關(guān)于java 數(shù)據(jù)類型的資料有很多,不夠全面,這里就整理下,需要的朋友可以參考下
    2017-01-01
  • Spring?IOC容器啟動示例分析

    Spring?IOC容器啟動示例分析

    這篇文章主要給大家介紹了Spring?IOC基于注解啟動的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • Spring @Configuration注解及配置方法

    Spring @Configuration注解及配置方法

    這篇文章主要介紹了Spring @Configuration注解及配置方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • java正則匹配讀取txt文件提取特定開頭和結(jié)尾的字符串

    java正則匹配讀取txt文件提取特定開頭和結(jié)尾的字符串

    通常我們可以直接通過文件流來讀取txt文件的內(nèi)容,但有時候也會遇到問題,下面這篇文章主要給大家介紹了關(guān)于java正則匹配讀取txt文件提取特定開頭和結(jié)尾的字符串的相關(guān)資料,需要的朋友可以參考下
    2022-11-11

最新評論