You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Stream使用groupingBy分组时如何对结果列表排序?

问题:分组后对列表按score降序排序

我使用Collectors.groupingBy将Student对象按年龄分组转换为StudentDTO列表,现有代码如下:

public class Test {
    public static void main(String[] args) {
        Student student1 = new Student(98,"man","CHEN",20);
        Student student2 = new Student(100,"man","PETER",20);
        Student student3 = new Student(100,"man","TMAC",21);
        ArrayList<Student> list = Lists.newArrayList(student1, student2, student3);

        Map<Integer, List<StudentDTO>> map = list.stream()
            .collect(Collectors.groupingBy(Student::getAge,
                Collectors.mapping(e -> new StudentDTO(e.getScore(), e.getName()),
                    Collectors.toList())
            ));

        System.out.println(map);
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class Student {
        private Integer score;
        private String sex;
        private String name;
        private Integer age;
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class StudentDTO {
        private Integer score;
        private String name;
    }
}

当前输出结果:

{20=[Test.StudentDTO(score=98, name=CHEN),
     Test.StudentDTO(score=100, name=PETER)],
 21=[Test.StudentDTO(score=100, name=TMAC)]}

期望输出(按score降序排序分组后的StudentDTO列表):

{20=[Test.StudentDTO(score=100, name=PETER),
     Test.StudentDTO(score=98, name=CHEN)],
 21=[Test.StudentDTO(score=100, name=TMAC)]}

解决方案

有两种常用方式实现需求:

方式一:收集阶段直接排序(推荐)

在groupingBy的下游收集器中,通过Collectors.collectingAndThen将收集到的列表立即排序。把原代码中的Collectors.toList()替换为包含排序逻辑的收集器即可:

Map<Integer, List<StudentDTO>> map = list.stream()
    .collect(Collectors.groupingBy(Student::getAge,
        Collectors.mapping(e -> new StudentDTO(e.getScore(), e.getName()),
            Collectors.collectingAndThen(Collectors.toList(), 
                list -> {
                    list.sort(Comparator.comparing(StudentDTO::getScore).reversed());
                    return list;
                }
            )
        )
    ));

方式二:分组后遍历排序

先按原有逻辑完成分组,再遍历Map的所有值,对每个分组列表单独排序:

// 原分组逻辑不变
Map<Integer, List<StudentDTO>> map = list.stream()
    .collect(Collectors.groupingBy(Student::getAge,
        Collectors.mapping(e -> new StudentDTO(e.getScore(), e.getName()),
            Collectors.toList())
    ));

// 对每个分组的列表按score降序排序
map.values().forEach(list -> 
    list.sort(Comparator.comparing(StudentDTO::getScore).reversed())
);

两种方式对比

  • 方式一:在流式收集过程中完成排序,逻辑更紧凑,属于一站式处理。
  • 方式二:步骤拆分清晰,适合需要在排序前对分组结果做其他额外处理的场景。

内容的提问来源于stack exchange,提问作者jane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 00:25:19