首页 > 其他分享 > Stream - Collectors.groupingBy实现分组后,且每个分组也进行排序

Stream - Collectors.groupingBy实现分组后,且每个分组也进行排序

时间:2023-07-12 17:44:54浏览次数:44  
标签:Stream Collectors System score 分组 Student println id

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

 

Stream - 实现分组后,且每个分组也进行排序

 


前言

之前记录过:stream的三个常用方式(toMap,groupingBy,findFirst)。
这里继续记录下groupingBy的几个高级用法。

个人认为,最有分歧的是:实现分组,且每个分组也进行排序

这里要特别说明下:
从方法上看,分组之后,是不能对每个分组进行比较的(也就无法排序)
Collectors.groupingBy(Function<? super T, ? extends K> classifier,
Collector<? super T, A, D> downstream)
这里有两个思路:
1:提前排序,再进行分组
2:分组后,对Map进行处理,对其每个value排序

这主要列举了常用的:summingInt、counting、mapping、分组生序排序,分组降序排序


一、groupingBy高级用法

import com.alibaba.fastjson.JSONObject;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Test {

    public static void main(String[] args) {

        Student student1 = new Student(1, 1);
        Student student2 = new Student(1, 1);
        Student student3 = new Student(2, 2);
        Student student4 = new Student(2, 3);
        Student student5 = new Student(3, 3);
        Student student6 = new Student(3, 4);
        Student student7 = new Student(4, 1);
        Student student8 = new Student(4, 1);
        Student student9 = new Student(4, 2);
        Student student10 = new Student(4, 1);

        List<Student> list = Arrays.asList(student1, student2, student3, student4, student5, student6, student7, student8, student9, student10);
        System.out.println("--------- 根据字段分组,求每个分组的sum ----------");
        Map<Integer, Integer> collect = list.stream().collect(Collectors.groupingBy(Student::getId, Collectors.summingInt(Student::getScore)));
        System.out.println(collect.toString());

        System.out.println("--------- 根据字段分组,求每个分组的count ----------");
        Map<Integer, Long> countMap = list.stream().collect(Collectors.groupingBy(Student::getId, Collectors.counting()));
        System.out.println(countMap.toString());

        System.out.println("--------- 根据字段分组,每个分组为:对象的指定字段 ----------");
        Map<Integer, List<Integer>> groupMap = list.stream().collect(Collectors.groupingBy(Student::getId, Collectors.mapping(Student::getScore, Collectors.toCollection(ArrayList::new))));
        System.out.println(groupMap.toString());

        System.out.println("--------- 根据字段分组,默认分组 ----------");
        Map<Integer, List<Student>> defaultGroupMap = list.stream().collect(Collectors.groupingBy(Student::getId));
        System.out.println(JSONObject.toJSONString(defaultGroupMap));

        System.out.println("--------- 根据字段分组,每个分组按照指定字段进行生序排序 ----------");
        Map<Integer, List<Student>> sortGroupMap = list.stream().sorted(Comparator.comparing(Student::getScore))
                .collect(Collectors.groupingBy(Student::getId));
        System.out.println(JSONObject.toJSONString(sortGroupMap));

        System.out.println("--------- 先排序,再分组 ----------");
        Map<Integer, List<Student>> reversedSortGroupMap = list.stream().sorted(Comparator.comparing(Student::getScore).reversed())
                .collect(Collectors.groupingBy(Student::getId));
        System.out.println(JSONObject.toJSONString(reversedSortGroupMap));


    }
}

class Student {

    private Integer id;

    private Integer score;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getScore() {
        return score;
    }

    public void setScore(Integer score) {
        this.score = score;
    }

    public Student(Integer id, Integer score) {
        this.id = id;
        this.score = score;
    }
}
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82

执行结果

--------- 根据字段分组,求每个分组的sum ----------
{1=2, 2=5, 3=7, 4=5}
--------- 根据字段分组,求每个分组的count ----------
{1=2, 2=2, 3=2, 4=4}
--------- 根据字段分组,每个分组为:对象的指定字段 ----------
{1=[1, 1], 2=[2, 3], 3=[3, 4], 4=[1, 1, 2, 1]}
--------- 根据字段分组,默认分组 ----------
{1:[{"id":1,"score":1},{"id":1,"score":1}],2:[{"id":2,"score":2},{"id":2,"score":3}],3:[{"id":3,"score":3},{"id":3,"score":4}],4:[{"id":4,"score":1},{"id":4,"score":1},{"id":4,"score":2},{"id":4,"score":1}]}
--------- 根据字段分组,每个分组按照指定字段进行生序排序 ----------
{1:[{"id":1,"score":1},{"id":1,"score":1}],2:[{"id":2,"score":2},{"id":2,"score":3}],3:[{"id":3,"score":3},{"id":3,"score":4}],4:[{"id":4,"score":1},{"id":4,"score":1},{"id":4,"score":1},{"id":4,"score":2}]}
---------  先排序,再分组  ----------
{1:[{"id":1,"score":1},{"id":1,"score":1}],2:[{"id":2,"score":3},{"id":2,"score":2}],3:[{"id":3,"score":4},{"id":3,"score":3}],4:[{"id":4,"score":2},{"id":4,"score":1},{"id":4,"score":1},{"id":4,"score":1}]}
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

二、先分组,再排序

先将数据进行groupingBy,得到Map<Long, List>。
在通过forEach对每个List进行排序

        Map<Long, List<StreamMapEntity>> map = getMap();
        System.out.println("------ flatMap 处理Map<Long,List<StreamMapEntity>> ------");
        System.out.println();
        System.out.println("初始数据:" + JSONObject.toJSONString(map));
        System.out.println();

        map.keySet().forEach(key -> map.computeIfPresent(key, (k, v) -> v.stream().sorted(Comparator.comparing(StreamMapEntity::getId).reversed()).collect(Collectors.toList())));
        System.out.println("处理map:对map内的每个list进行排序:");
        System.out.println(JSONObject.toJSONString(map));
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

执行结果:

------ flatMap 处理Map<Long,List<StreamMapEntity>> ------

初始数据:{1111:[{"id":1,"name":"aa"},{"id":2,"name":"bb"},{"id":3,"name":"cc"},{"id":4,"name":"dd"}],2222:[{"id":5,"name":"ee"},{"id":6,"name":"ff"},{"id":7,"name":"gg"},{"id":8,"name":"hh"}]}


处理map:对map内的每个list进行排序:
{1111:[{"id":4,"name":"dd"},{"id":3,"name":"cc"},{"id":2,"name":"bb"},{"id":1,"name":"aa"}],2222:[{"id":8,"name":"hh"},{"id":7,"name":"gg"},{"id":6,"name":"ff"},{"id":5,"name":"ee"}]}
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

总结

关于分组排序的两种方式:先排序再分组;先分组再排序。

效率上肯定是先排序再分组快。

标签:Stream,Collectors,System,score,分组,Student,println,id
From: https://www.cnblogs.com/tiancai/p/17548354.html

相关文章

  • Java8新特性之parallelStream详解
    一、什么是流?Stream是java8中新增加的一个特性,首先Stream不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本的Iterator。原始版本的Iterator,用户只能显式地一个一个遍历元素并对其执行某些操作;高级版本的Stream,用户只要给出需要对其包含的元素......
  • 使用Java8 Stream流中的Collectors.collectingAndThen()方法去重
    https://blog.csdn.net/qq_40474184/article/details/122043378Stream流的常用方法大全https://blog.csdn.net/weixin_52317961/article/details/128117727......
  • stream
    stream由来为了抢消息队列的饭碗原理1MessageContent消息内容2Consumergroup消费组,通过XGROUPCREATE命令创建,同一个消费组可以有多个消费者3Last_delivered_id游标,每个消费组会有个游标last_delivered_id,任意一个消费者读取了消息都会使游标last_deli......
  • 分组查询时,select的字段是否一定要都在group by中
    分组查询时,select的字段是否一定要都在groupby中?分组查询关键字groupby通常和集合函数(MAX、MIN、COUNT、SUM、AVG)一起使用,它可以对一列或者多列结果集进行分组。例如要统计超市水果的种类,需要用count函数,要统计哪个水果价格最高,要用MAX()函数。一般情况下,我们在使用groupby的......
  • Streamlit 入门介绍
    Streamlit入门介绍Streamlit是一个PythonWeb应用框架。但和常规Web框架,如Flask/Django的不同之处在于,它不需要你去编写任何客户端代码(HTML/CSS/JS),只需要编写普通的Python模块,就可以在很短的时间内创建美观并具备高度交互性的界面,从而快速生成数据分析或者机器学习的结......
  • 【NSSCTF逆向】【2023题目】《stream》《a_cup_of_tea》
    总览streamRC4base64exe解包pyc反编译a_cup_of_teatea题目stream解法拿到题目是一个exe,先用exeinfo打开看看可以看到这个程序使用python写的,又是exe。所以就是常规的思路,exe解包到pyc文件,再对pyc文件进行反编译先是解包用pyinstxtractor.py里面找到它再来反编......
  • Collectors全部的方法
    Collectors类提供了很多方法来进行汇总和收集操作。以下是Collectors类中的全部方法:toList():将流中的元素收集到一个List集合中。toSet():将流中的元素收集到一个Set集合中。toMap(Function<?superT,?extendsK>keyMapper,Function<?superT,?extendsU>valueMap......
  • Java获取名字首字母拼音及用户按名字拼音分组工具
    一、需求分析最近在做一个类似于微信用户通讯录的功能,所以考虑通过查找的好友列表,在后台遍历按照26个字母分组,前台获取到Json循环26个字母直接解析对应的字符下的名称为一组分隔,没有则不显示,工具如下↓二、引入Pom<dependency> <groupId>com.belerweb</groupId> <artif......
  • 关于Stream流的一些常用方法
    前言在这里先说明一下,这个重在应用,本文就不对概念跟描述做过多赘述。应用1)提取对象数组中的某一个字段(带去重)List<String>orderIdList=orderList.stream().map(e->e.getOrderId()).distinct().collect(Collectors.toList());//收集全部orderIdSetthirdCategoryI......
  • Spark 以及 spark streaming 核心原理及实践 - (2)
    SparkStreaming运行原理spark程序是使用一个spark应用实例一次性对一批历史数据进行处理,sparkstreaming是将持续不断输入的数据流转换成多个batch分片,使用一批spark应用实例进行处理。从原理上看,把传统的spark批处理程序变成streaming程序,spark需要构建什么?需要构建4个东西:一个静......