Java8?stream流分組groupingBy的使用方法代碼
眾所周知,使用stream流可以讓我們的代碼看上去很簡(jiǎn)潔,現(xiàn)在我們實(shí)戰(zhàn)使用一下stream的分組與分區(qū)。
準(zhǔn)備用到的數(shù)據(jù)類 public class Student{ //年級(jí) private String grade; //班級(jí) private String classNumber; //姓名 private String name; //年齡 private int age; //地址 private String address; //數(shù)學(xué)成績 private int mathScores; //語文成績 private int chainessScores; } 添加數(shù)據(jù) Student student1 = new Student("701","張三",16,"北京",78,90); Student student2 = new Student("700","李四",17,"北京",78,90); Student student3 = new Student("703","王五",16,"上海",78,90); Student student4 = new Student("701","趙六",16,"上海",78,90); Student student5 = new Student("700","錢七",18,"",78,90); Student student6 = new Student("701","老八",17,"",78,90); //這是一個(gè)高二年級(jí)的成績單 List<Student> students = Stream.of(student1,student2,student3,student4,student5,student6).collect(Collectors.toList());
按照班級(jí)分組
Map<String, List<Student>> collect = students.stream().collect(Collectors.groupingBy(Student::getClassNumber)); System.out.println(JSON.toJSONString(collect)); //{"700":[{"age":17,"chainessScores":90,"classNumber":"700","mathScores":78,"name":"李四"},{"age":18,"chainessScores":90,"classNumber":"700","mathScores":78,"name":"錢七"}], //"701":[{"age":16,"chainessScores":90,"classNumber":"701","mathScores":78,"name":"張三"},{"age":16,"chainessScores":90,"classNumber":"701","mathScores":78,"name":"趙六"},{"age":17,"chainessScores":90,"classNumber":"701","mathScores":78,"name":"老八"}], //"703":[{"age":16,"chainessScores":90,"classNumber":"703","mathScores":78,"name":"王五"}]}
按照班級(jí)分組得到每個(gè)班級(jí)的同學(xué)姓名
Map<String, List<String>> collect = students.stream().collect(Collectors.groupingBy(Student::getClassNumber, Collectors.mapping(Student::getName, Collectors.toList()))); System.out.println(JSON.toJSONString(collect)); //{"700":["李四","錢七"],"701":["張三","趙六","老八"],"703":["王五"]}
統(tǒng)計(jì)每個(gè)班級(jí)人數(shù)
Map<String, Long> collect = students.stream().collect(Collectors.groupingBy(Student::getClassNumber, Collectors.counting())); System.out.println(JSON.toJSONString(collect)); //{"700":2,"701":3,"703":1}
求每個(gè)班級(jí)的數(shù)學(xué)平均成績
Map<String, Double> collect = students.stream().collect(Collectors.groupingBy(Student::getClassNumber, Collectors.averagingDouble(Student::getMathScores))); System.out.println(JSON.toJSONString(collect)); //{"700":65.0,"701":61.0,"703":82.0}
按班級(jí)分組求每個(gè)同學(xué)的總成績
Map<String, Map<String, Integer>> collect = students.stream().collect(Collectors.groupingBy(Student::getClassNumber, Collectors.toMap(Student::getName, student -> student.getMathScores() + student.getChainessScores()))); System.out.println(JSON.toJSONString(collect)); //{"700":{"錢七":150,"李四":160},"701":{"張三":168,"老八":148,"趙六":137},"703":{"王五":172}}
嵌套分組,先按班級(jí)分組,再按年齡分組
Map<String, Map<Integer, List<Student>>> collect = students.stream().collect(Collectors.groupingBy(Student::getClassNumber, Collectors.groupingBy(Student::getAge)));
分組后得到一個(gè)線程安全的ConcurrentMap
ConcurrentMap<String, List<Student>> collect = students.stream().collect(Collectors.groupingByConcurrent(Student::getClassNumber));
加上排序來一波
根據(jù)年齡分組并小到大排序,TreeMap默認(rèn)為按照key升序
TreeMap<Integer, List<String>> collect = students.stream().collect(Collectors.groupingBy(Student::getAge, TreeMap::new, Collectors.mapping(Student::getName, Collectors.toList()))); System.out.println(JSON.toJSONString(collect)); //{16:["張三","王五","趙六"],17:["李四","老八"],18:["錢七"]}
根據(jù)年齡分組并大到小排序,因?yàn)門reeMap默認(rèn)為按照key升序,所以排完順序再反轉(zhuǎn)一下就OK了
TreeMap<Integer, List<String>> collect = students.stream().collect(Collectors.groupingBy(Student::getAge, TreeMap::new, Collectors.mapping(Student::getName, Collectors.toList()))); Map<Integer, List<String>> collect2 = collect.descendingMap(); System.out.println(JSON.toJSONString(collect2)); //{18:["錢七"],17:["李四","老八"],16:["張三","王五","趙六"]}
附:高級(jí)用法
只是個(gè)人感覺比上面的高級(jí)一些,可能在大佬看來本質(zhì)上都一樣,只是更復(fù)雜了一點(diǎn)點(diǎn)。
1. 改變分組后的key和value
在上面的分組中,key還好,在4和5自定義條件分組中,改變了key。但是value呢?好像都是定死了,普通的分組就是該對(duì)象的集合,求和、統(tǒng)計(jì)就是一個(gè)數(shù)字,能不能我自己來規(guī)定返回的value類型呢?比如我要按照門派分組,得到每個(gè)門派里面每個(gè)人的名字,不需要其他的性別、年齡信息
代碼
// 按照門派分組,分組后 key 為Group對(duì)象, value變成String名字 Map<Group, List<String>> collect2 = users.stream() .collect(Collectors.groupingBy(x -> new Group(x.getGroup(), x.getGroup() + "的描述"), Collectors.mapping(User::getUsername, Collectors.toCollection(ArrayList::new))));
結(jié)果
{BlogMain1.Group(name=明教, desc=明教的描述)=[張無忌, 金毛獅王--謝遜, 紫衫龍王--黛綺絲, 白眉鷹王--殷天正, 青翼蝠王--韋一笑], BlogMain1.Group(name=武當(dāng), desc=武當(dāng)?shù)拿枋?=[張三豐, 宋遠(yuǎn)橋, 張翠山, 殷梨亭], BlogMain1.Group(name=少林, desc=少林的描述)=[圓真, 空智], BlogMain1.Group(name=峨眉, desc=峨眉的描述)=[滅絕師太, 周芷若, 宋青書]}
2. 多級(jí)分組
先按照一個(gè)條件分組,在分組的基礎(chǔ)上再按照另一個(gè)條件分組
代碼
// 多級(jí)分組,先按照門派分組,門派里面再按照名字長度分組 Map<Group, Map<Integer, List<User>>> collect3 = users.stream().collect( Collectors.groupingBy(x -> new Group(x.getGroup(), x.getGroup() + "的描述"), Collectors.groupingBy(x -> x.username.length())));
結(jié)果
{BlogMain1.Group(name=明教, desc=明教的描述)={3=[BlogMain1.User(username=張無忌, gender=男, group=明教, age=23)], 8=[BlogMain1.User(username=金毛獅王--謝遜, gender=男, group=明教, age=47)], 9=[BlogMain1.User(username=紫衫龍王--黛綺絲, gender=女, group=明教, age=32), BlogMain1.User(username=白眉鷹王--殷天正, gender=男, group=明教, age=38), BlogMain1.User(username=青翼蝠王--韋一笑, gender=男, group=明教, age=35)]}, BlogMain1.Group(name=武當(dāng), desc=武當(dāng)?shù)拿枋?={3=[BlogMain1.User(username=張三豐, gender=男, group=武當(dāng), age=56), BlogMain1.User(username=宋遠(yuǎn)橋, gender=男, group=武當(dāng), age=42), BlogMain1.User(username=張翠山, gender=男, group=武當(dāng), age=41), BlogMain1.User(username=殷梨亭, gender=男, group=武當(dāng), age=37)]}, BlogMain1.Group(name=少林, desc=少林的描述)={2=[BlogMain1.User(username=圓真, gender=男, group=少林, age=35), BlogMain1.User(username=空智, gender=男, group=少林, age=47)]}, BlogMain1.Group(name=峨眉, desc=峨眉的描述)={3=[BlogMain1.User(username=周芷若, gender=女, group=峨眉, age=21), BlogMain1.User(username=宋青書, gender=男, group=峨眉, age=22)], 4=[BlogMain1.User(username=滅絕師太, gender=女, group=峨眉, age=51)]}}
3. 分組排序
就是先分組, 再每組分別排序, 經(jīng)常寫SQL的小伙伴可能經(jīng)常碰到這個(gè)問題, steam api 就非常簡(jiǎn)單
代碼
Map<String, List<User>> userMap = users.stream().collect(Collectors.groupingBy(User::getGender, Collectors.mapping(u -> u, Collectors.collectingAndThen(Collectors.toList(), sortedStudents -> sortedStudents.stream().sorted((Comparator.comparing(User::getAge))) .collect(Collectors.toList()))))); userMap.forEach((k, v) -> { System.err.println("k: " + k); v.forEach(System.err::println); });
結(jié)果
k: 女
BlogMain1.User(username=周芷若, gender=女, group=峨眉, age=21)
BlogMain1.User(username=紫衫龍王--黛綺絲, gender=女, group=明教, age=32)
BlogMain1.User(username=滅絕師太, gender=女, group=峨眉, age=51)
k: 男
BlogMain1.User(username=宋青書, gender=男, group=峨眉, age=22)
BlogMain1.User(username=張無忌, gender=男, group=明教, age=23)
BlogMain1.User(username=青翼蝠王--韋一笑, gender=男, group=明教, age=35)
BlogMain1.User(username=圓真, gender=男, group=少林, age=35)
BlogMain1.User(username=殷梨亭, gender=男, group=武當(dāng), age=37)
BlogMain1.User(username=白眉鷹王--殷天正, gender=男, group=明教, age=38)
BlogMain1.User(username=張翠山, gender=男, group=武當(dāng), age=41)
BlogMain1.User(username=宋遠(yuǎn)橋, gender=男, group=武當(dāng), age=42)
BlogMain1.User(username=金毛獅王--謝遜, gender=男, group=明教, age=47)
BlogMain1.User(username=空智, gender=男, group=少林, age=47)
BlogMain1.User(username=張三豐, gender=男, group=武當(dāng), age=56)
4. 我在項(xiàng)目中的使用例子
總結(jié)
到此這篇關(guān)于Java8 stream流分組groupingBy使用的文章就介紹到這了,更多相關(guān)Java8 stream流分組groupingBy內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java實(shí)現(xiàn)兩人五子棋游戲(四) 落子動(dòng)作的實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)兩人五子棋游戲,落子動(dòng)作的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03java代碼實(shí)現(xiàn)C盤文件統(tǒng)計(jì)工具
今天周末,給大家分享基于java代碼實(shí)現(xiàn)C盤文件統(tǒng)計(jì)工具,在這小編使用的版本是Maven-3.9.9,jdk1.8,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-07-07JAVA加密算法- 非對(duì)稱加密算法(DH,RSA)的詳細(xì)介紹
這篇文章主要介紹了JAVA加密算法- 非對(duì)稱加密算法(DH,RSA),詳細(xì)介紹了DH,RSA的用法和示例,需要的朋友可以了解一下。2016-11-11pom.xml中解決Provides?transitive?vulnerable?dependency?mave
這篇文章主要介紹了在pom.xml中如何解決Provides?transitive?vulnerable?dependency?maven:org.yaml:snakeyaml:1.33警告問題,需要的朋友可以參考下2023-06-06Java遞歸簡(jiǎn)單實(shí)現(xiàn)n的階乘
這篇文章主要介紹了Java遞歸簡(jiǎn)單實(shí)現(xiàn)n的階乘,遞歸(recursion)就是子程序(或函數(shù))直接調(diào)用自己或通過一系列調(diào)用語句間接調(diào)用自己,是一種描述問題和解決問題的基本方法,下面我們舉一個(gè)小小的例子詳情了解一下,需要的朋友可以參考下2021-12-12通過第三方接口發(fā)送短信驗(yàn)證碼/短信通知(推薦)
這篇文章主要介紹了通過第三方接口發(fā)送短信驗(yàn)證碼/短信通知(推薦)的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-08-08