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
相关产品推荐
相关产品推荐

