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

前言

之前记录过: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;
    }
}

执行结果

--------- 根据字段分组,求每个分组的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}]}

二、先分组,再排序

先将数据进行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));

执行结果:

------ 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"}]}

总结

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

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

猜你喜欢

转载自blog.csdn.net/qq_43842093/article/details/131506920