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

一文詳解Java中的Stream的匯總和分組操作

 更新時(shí)間:2022年09月01日 08:33:15   作者:寧在春  
這篇文章主要為大家詳細(xì)介紹了Java8中的Stream的匯總和分組的操作,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java有一定幫助,需要的可以參考一下

前言

在前面的文章中其實(shí)大家也已經(jīng)看到我使用過(guò)collect(Collectors.toList()) 將數(shù)據(jù)最后匯總成一個(gè) List 集合。

但其實(shí)還可以轉(zhuǎn)換成Integer、Map、Set 集合等。

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

     static List<Student> students = new ArrayList<>();
 ?
     static {
         students.add(new Student("學(xué)生A", "大學(xué)A", 18, 98.0));
         students.add(new Student("學(xué)生B", "大學(xué)A", 18, 91.0));
         students.add(new Student("學(xué)生C", "大學(xué)A", 18, 90.0));
         students.add(new Student("學(xué)生D", "大學(xué)B", 18, 76.0));
         students.add(new Student("學(xué)生E", "大學(xué)B", 18, 91.0));
         students.add(new Student("學(xué)生F", "大學(xué)B", 19, 65.0));
         students.add(new Student("學(xué)生G", "大學(xué)C", 20, 80.0));
         students.add(new Student("學(xué)生H", "大學(xué)C", 21, 78.0));
         students.add(new Student("學(xué)生I", "大學(xué)C", 20, 67.0));
         students.add(new Student("學(xué)生J", "大學(xué)D", 22, 87.0));
     }
 ?
     public static void main(String[] args) {
         Optional<Student> collect1 = students.stream().collect(Collectors.maxBy((s1, s2) -> s1.getAge() - s2.getAge()));
         Optional<Student> collect2 = students.stream().collect(Collectors.minBy((s1, s2) -> s1.getAge() - s2.getAge()));
         Student max = collect1.get();
         Student min = collect2.get();
         System.out.println("max年齡的學(xué)生==>" + max);
         System.out.println("min年齡的學(xué)生==>" + min);
         /**
          * max年齡的學(xué)生==>Student(name=學(xué)生J, school=大學(xué)D, age=22, score=87.0)
          * min年齡的學(xué)生==>Student(name=學(xué)生A, school=大學(xué)A, age=18, score=98.0)
          */
     }

Optional,它是一個(gè)容器,可以包含也可以不包含值。它是java8中人們常說(shuō)的優(yōu)雅的判空的操作。

另一個(gè)常見(jiàn)的返回單個(gè)值的歸約操作是對(duì)流中對(duì)象的一個(gè)數(shù)值字段求和?;蛘吣憧赡芟胍?平均數(shù)。這種操作被稱(chēng)為匯總操作。讓我們來(lái)看看如何使用收集器來(lái)表達(dá)匯總操作。

二、匯總

Collectors類(lèi)專(zhuān)門(mén)為匯總提供了一些個(gè)工廠方法:

當(dāng)然除此之外還有 求平均數(shù)averagingDouble、求總數(shù)counting等等

我們暫且就先以summingDoublesummarizingDouble來(lái)舉例吧

案例數(shù)據(jù)仍然是上面的那些student數(shù)據(jù)...

求全部學(xué)生成績(jī)的總分,求全部學(xué)生的平均分。

1、首先使用summingDoubleaveragingDouble 來(lái)實(shí)現(xiàn)

 Double summingScore = students.stream().collect(Collectors.summingDouble(Student::getScore));
 Double averagingScore = students.stream().collect(Collectors.averagingDouble(Student::getScore));
 System.out.println("學(xué)生的總分==>" + summingScore);
 System.out.println("學(xué)生的平均分==>" + averagingScore);
 /**
 * 學(xué)生的總分==>823.0
  * 學(xué)生的平均分==>82.3
 */

2、使用summarizingDouble來(lái)實(shí)現(xiàn)

它更為綜合,可以直接計(jì)算出相關(guān)的匯總信息

 DoubleSummaryStatistics summarizingDouble = students.stream().collect(Collectors.summarizingDouble(Student::getScore));
 ?
 double sum = summarizingDouble.getSum();
 long count = summarizingDouble.getCount();
 double average = summarizingDouble.getAverage();
 double max = summarizingDouble.getMax();
 double min = summarizingDouble.getMin();
 System.out.println("sum==>"+sum);
 System.out.println("count==>"+count);
 System.out.println("average==>"+average);
 System.out.println("max==>"+max);
 System.out.println("min==>"+min);
 /**
  * sum==>823.0
  * count==>10
  * average==>82.3
  * max==>98.0
  * min==>65.0
  */

但其實(shí)大家也都發(fā)現(xiàn)了,使用一個(gè)接口能夠?qū)崿F(xiàn),也可以拆開(kāi)根據(jù)自己的所需,選擇合適的API來(lái)實(shí)現(xiàn),具體的使用還是需要看使用場(chǎng)景。

三、連接字符串

Joining,就是把流中每一個(gè)對(duì)象應(yīng)用toString方法得到的所有字符串連接成一個(gè)字符串。

如果這么看,它其實(shí)沒(méi)啥用,但是Java也留下了后招,它的同伴(重載方法)提供了一個(gè)可以接受元素之間的分割符的方法。

 ?
         String studentsName = students.stream().map(student -> student.getName()).collect(Collectors.joining());
         System.out.println(studentsName);
         String studentsName2 = students.stream().map(student -> student.getName()).collect(Collectors.joining(","));
         System.out.println(studentsName2);
         /**
          * 學(xué)生A學(xué)生B學(xué)生C學(xué)生D學(xué)生E學(xué)生F學(xué)生G學(xué)生H學(xué)生I學(xué)生J
          * 學(xué)生A,學(xué)生B,學(xué)生C,學(xué)生D,學(xué)生E,學(xué)生F,學(xué)生G,學(xué)生H,學(xué)生I,學(xué)生J
          */

對(duì)于對(duì)象的打?。?/p>

 // 不過(guò)對(duì)于對(duì)象的打印 個(gè)人感覺(jué)還好 哈哈
 String collect = students.stream().map(student -> student.toString()).collect(Collectors.joining(","));
 System.out.println(collect);
 System.out.println(students);
 /**
          * Student(name=學(xué)生A, school=大學(xué)A, age=18, score=98.0),Student(name=學(xué)生B, school=大學(xué)A, age=18, score=91.0),Student(name=學(xué)生C, school=大學(xué)A, age=18, score=90.0),Student(name=學(xué)生D, school=大學(xué)B, age=18, score=76.0),Student(name=學(xué)生E, school=大學(xué)B, age=18, score=91.0)....
          * [Student(name=學(xué)生A, school=大學(xué)A, age=18, score=98.0), Student(name=學(xué)生B, school=大學(xué)A, age=18, score=91.0), Student(name=學(xué)生C, school=大學(xué)A, age=18, score=90.0), Student(name=學(xué)生D, school=大學(xué)B, age=18, score=76.0)..)]
          */

但其實(shí)我還有一些沒(méi)有講到的API使用方法,大家也可以額外去嘗試嘗試,這其實(shí)遠(yuǎn)比你看這篇文章吸收的更快~

四、分組

就像數(shù)據(jù)庫(kù)中的分組統(tǒng)計(jì)一樣~

1、分組

舉個(gè)例子,我想統(tǒng)計(jì)每個(gè)學(xué)校有哪些學(xué)生

我是不是得設(shè)計(jì)這樣的一個(gè)數(shù)據(jù)結(jié)構(gòu)Map<String,List<Student>>才能存放勒,我在循環(huán)的時(shí)候,是不是每次都得判斷一下學(xué)生所在的學(xué)校的名稱(chēng),然后看是否要給它添加到這個(gè)List集合中去,最后再put到map中去呢?

看著就特別繁瑣,但是在 stream 中就變成了一行代碼,其他的東西,都是 Java 內(nèi)部給你優(yōu)化了

         // 我想知道每所學(xué)校中,學(xué)生的數(shù)量及相關(guān)信息,只要這一行代碼即可
         Map<String, List<Student>> collect = students.stream().collect(Collectors.groupingBy(Student::getSchool));
         System.out.println(collect);
         /**
          * {大學(xué)B=[Student(name=學(xué)生D, school=大學(xué)B, age=18, score=76.0), Student(name=學(xué)生E, school=大學(xué)B, age=18, score=91.0), Student(name=學(xué)生F, school=大學(xué)B, age=19, score=65.0)],
          * 大學(xué)A=[Student(name=學(xué)生A, school=大學(xué)A, age=18, score=98.0), Student(name=學(xué)生B, school=大學(xué)A, age=18, score=91.0), Student(name=學(xué)生C, school=大學(xué)A, age=18, score=90.0)],
          * 大學(xué)D=[Student(name=學(xué)生J, school=大學(xué)D, age=22, score=87.0)],
          * 大學(xué)C=[Student(name=學(xué)生G, school=大學(xué)C, age=20, score=80.0), Student(name=學(xué)生H, school=大學(xué)C, age=21, score=78.0), Student(name=學(xué)生I, school=大學(xué)C, age=20, score=67.0)]}
          */

有些時(shí)候這真的是十分有用且方便的。

但是有時(shí)候我們往往不止于如此,假如我要統(tǒng)計(jì)每個(gè)學(xué)校中20歲年齡以上和20以下的學(xué)生分別有哪些學(xué)生,那么我的參數(shù)就不再是Student::getSchool了,而是要加上語(yǔ)句了。那么該如何編寫(xiě)呢?

 //統(tǒng)計(jì)每個(gè)學(xué)校中20歲年齡以上和20以下的學(xué)生分別有多少
 Map<String, List<Student>> collect = students.stream().collect(Collectors.groupingBy(student -> {
     if (student.getAge() > 20) {
         return "20歲以上的";
     }
     return "20以下的";
 }));
 System.out.println(collect);

如果要統(tǒng)計(jì)每個(gè)學(xué)校有多少20歲以上和20歲以下的學(xué)生的信息,其實(shí)也就是把 return 語(yǔ)句修改以下即可。

 //統(tǒng)計(jì)每個(gè)學(xué)校中20歲年齡以上和20以下的學(xué)生分別有多少
 Map<String, List<Student>> collect = students.stream().collect(Collectors.groupingBy(student -> {
     if (student.getAge() > 20) {
         return student.getSchool();
     }
     return student.getSchool();
 }));
 System.out.println(collect);

相信大家也看出來(lái)groupingBy中的 return 語(yǔ)句就是 Map 中的key值

2、多級(jí)分組

但其實(shí)groupingBy()并不只是一個(gè)人,它也有兄弟姐妹

假如我想把上面的例子再改造改造,

改為:我想知道20歲以上的學(xué)生在每個(gè)學(xué)校有哪些學(xué)生,20歲以下的學(xué)生在每個(gè)學(xué)校有哪些學(xué)生。

數(shù)據(jù)結(jié)構(gòu)就應(yīng)當(dāng)設(shè)計(jì)為Map<String, Map<String, List<Student>>> 啦,第一級(jí)存放 20歲以上以下兩組數(shù)據(jù),第二級(jí)存放以每個(gè)學(xué)校名為key的數(shù)據(jù)信息。

 Map<String, Map<String, List<Student>>> collect = students.stream().collect(Collectors.groupingBy(Student::getSchool, Collectors.groupingBy(student -> {
     if (student.getAge() > 20) {
         return "20以上的";
     }
     return "20歲以下的";
 })));
 System.out.println(collect);
 /**
          * {大學(xué)B={20歲以下的=[Student(name=學(xué)生D, school=大學(xué)B, age=18, score=76.0),Student(name=學(xué)生E, school=大學(xué)B, age=18, score=91.0), Student(name=學(xué)生F, school=大學(xué)B, age=19, score=65.0)]},
          * 大學(xué)A={20歲以下的=[Student(name=學(xué)生A, school=大學(xué)A, age=18, score=98.0), Student(name=學(xué)生B, school=大學(xué)A, age=18, score=91.0), Student(name=學(xué)生C, school=大學(xué)A, age=18, score=90.0)]}, 
          * 大學(xué)D={20以上的=[Student(name=學(xué)生J, school=大學(xué)D, age=22, score=87.0)]}, 
          * 大學(xué)C={20以上的=[Student(name=學(xué)生H, school=大學(xué)C, age=21, score=78.0)],20歲以下的=[Student(name=學(xué)生G, school=大學(xué)C, age=20, score=80.0), Student(name=學(xué)生I, school=大學(xué)C, age=20, score=67.0)]}}
          */

這里利用的就是把一個(gè)內(nèi)層groupingBy傳遞給外層groupingBy,俗稱(chēng)的套娃~

外層Map的鍵就是第一級(jí)分類(lèi)函數(shù)生成的值,而這個(gè)Map的值又是一個(gè)Map,鍵是二級(jí)分類(lèi)函數(shù)生成的值。

3、按子組數(shù)據(jù)進(jìn)行劃分

之前我的截圖中,groupingBy的重載方法中,其實(shí)對(duì)于第二個(gè)參數(shù)的限制,并非說(shuō)一定是要groupingBy類(lèi)型的收集,更抽象點(diǎn)說(shuō),它可以是任意的收集器~

再假如,我的例子改為:

我現(xiàn)在明確的想知道每個(gè)學(xué)校20歲的學(xué)生的人數(shù)。

那么這個(gè)數(shù)據(jù)結(jié)構(gòu)就應(yīng)當(dāng)改為

Map<String,Long>或者是Map<String,Integer>呢?

那么在這里該如何實(shí)現(xiàn)呢?

 Map<String, Long> collect = students.stream().collect(Collectors.groupingBy(Student::getSchool, Collectors.counting()));
 System.out.println(collect);
 /**
 * {大學(xué)B=3, 大學(xué)A=3, 大學(xué)D=1, 大學(xué)C=3}
 */

實(shí)際上還有許多未曾談到的東西,這里都只是非常簡(jiǎn)單的應(yīng)用,對(duì)于其中的流的執(zhí)行的先后順序,以及一些簡(jiǎn)單的原理,都沒(méi)有過(guò)多的涉及,大家先上手用著吧~

后記

我這里只是闡述了一些比較簡(jiǎn)單的應(yīng)用性操作,未談及設(shè)計(jì)思想之類(lèi),但是要明白那種才是更值得去閱讀和理解的。

到此這篇關(guān)于一文詳解Java中的Stream的匯總和分組操作的文章就介紹到這了,更多相關(guān)Java Stream匯總 分組內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • HttpClient基礎(chǔ)解析

    HttpClient基礎(chǔ)解析

    這篇文章主要介紹了HttpClient基礎(chǔ)知識(shí),算是比較詳細(xì)地對(duì)知識(shí)點(diǎn)和相關(guān)實(shí)例進(jìn)行解釋,需要的朋友可以參考下
    2017-09-09
  • mybatis 忽略實(shí)體對(duì)象的某個(gè)屬性(2種方式)

    mybatis 忽略實(shí)體對(duì)象的某個(gè)屬性(2種方式)

    這篇文章主要介紹了mybatis 忽略實(shí)體對(duì)象的某個(gè)屬性方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • JavaBean實(shí)體類(lèi)處理外鍵過(guò)程解析

    JavaBean實(shí)體類(lèi)處理外鍵過(guò)程解析

    這篇文章主要介紹了JavaBean實(shí)體類(lèi)處理外鍵過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • java調(diào)用百度的接口獲取起-止位置的距離

    java調(diào)用百度的接口獲取起-止位置的距離

    本文主要介紹了java調(diào)用百度的接口獲取起-止位置的距離,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • SpringBoot2.0+阿里巴巴Sentinel動(dòng)態(tài)限流實(shí)戰(zhàn)(附源碼)

    SpringBoot2.0+阿里巴巴Sentinel動(dòng)態(tài)限流實(shí)戰(zhàn)(附源碼)

    這篇文章主要介紹了SpringBoot2.0+阿里巴巴Sentinel動(dòng)態(tài)限流實(shí)戰(zhàn)(附源碼),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Java構(gòu)造函數(shù)里的一些坑記錄super()和this()

    Java構(gòu)造函數(shù)里的一些坑記錄super()和this()

    這篇文章主要介紹了Java構(gòu)造函數(shù)里的一些坑記錄super()和this(),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • Java數(shù)組使用binarySearch()方法查找指定元素的實(shí)現(xiàn)

    Java數(shù)組使用binarySearch()方法查找指定元素的實(shí)現(xiàn)

    這篇文章主要介紹了Java數(shù)組使用binarySearch()方法查找指定元素的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Java之Spring簡(jiǎn)單的讀取和存儲(chǔ)對(duì)象

    Java之Spring簡(jiǎn)單的讀取和存儲(chǔ)對(duì)象

    這篇文章主要介紹了Spring的讀取和存儲(chǔ)對(duì)象,獲取 bean 對(duì)象也叫做對(duì)象裝配,是把對(duì)象取出來(lái)放到某個(gè)類(lèi)中,有時(shí)候也叫對(duì)象注?,想進(jìn)一步了解的同學(xué)可以參考本文
    2023-04-04
  • SpringBoot+WebSocket實(shí)現(xiàn)消息推送功能

    SpringBoot+WebSocket實(shí)現(xiàn)消息推送功能

    WebSocket協(xié)議是基于TCP的一種新的網(wǎng)絡(luò)協(xié)議。本文將通過(guò)SpringBoot集成WebSocket實(shí)現(xiàn)消息推送功能,感興趣的可以了解一下
    2022-08-08
  • Java集合繼承體系詳解

    Java集合繼承體系詳解

    這篇文章主要為大家詳細(xì)介紹了Java集合繼承體系,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11

最新評(píng)論