Stream流的groupingBy

Stream流的groupingBy

简单使用

业务场景:现在有100个人,这些人都年龄分部在18-30岁之间。现要求把他们按照年龄进行分组

key:年龄

value:数据列表

java 复制代码
public void listToMapGroup() {
		//这里假设通过listStreamService.list();方法查询了这100人
        List<Perple> list = perpleService.list();
        
        //按照age进行分组
        Map<Integer, List<Perple>> result = list.stream()
                .collect(Collectors.groupingBy(Perple::getAge));
                
        //打印结果
        result.forEach((k, v) -> {
            System.out.println(k);
            System.out.println(v);
            System.out.println("--------------------");
        });
}

效果相当于是,把list这个集合里面存放的100个人每个人都调用Perple的getAge方法,按照getAge方法的返回值进行分组。每个组是一个Map<Integer, List>类型的对象。Map<Integer, List>的键是getAge的返回值,即,分组的依据。Map<Integer, List>的值是这个年龄对应组中的成员。

如果要进行排序

分组之后,是不能对每个分组进行比较的(也就无法排序),因为groupingBy是一个终结流。

Collectors.groupingBy(Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream)

这里有两个思路:

1:提前排序,再进行分组

2:分组后,对Map进行处理,对其每个value排序

做法一:

提前排序,再进行分组.

这里还展示了一些groupingBy方法的扩展用法。

java 复制代码
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;
    }
}

执行结果:

java 复制代码
--------- 根据字段分组,求每个分组的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进行排序

java 复制代码
        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));

执行结果:

java 复制代码
------ 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"}]}
相关推荐
陈王卜15 分钟前
django+boostrap实现发布博客权限控制
java·前端·django
小码的头发丝、16 分钟前
Spring Boot 注解
java·spring boot
java亮小白199721 分钟前
Spring循环依赖如何解决的?
java·后端·spring
飞滕人生TYF27 分钟前
java Queue 详解
java·队列
武子康1 小时前
大数据-230 离线数仓 - ODS层的构建 Hive处理 UDF 与 SerDe 处理 与 当前总结
java·大数据·数据仓库·hive·hadoop·sql·hdfs
武子康1 小时前
大数据-231 离线数仓 - DWS 层、ADS 层的创建 Hive 执行脚本
java·大数据·数据仓库·hive·hadoop·mysql
苏-言1 小时前
Spring IOC实战指南:从零到一的构建过程
java·数据库·spring
界面开发小八哥1 小时前
更高效的Java 23开发,IntelliJ IDEA助力全面升级
java·开发语言·ide·intellij-idea·开发工具
草莓base1 小时前
【手写一个spring】spring源码的简单实现--容器启动
java·后端·spring
Allen Bright2 小时前
maven概述
java·maven