
本文介绍如何将 Java 中通过 Collectors.groupingBy 分组得到的 Collection 按各子列表元素数量从多到少排序,核心是结合 Stream.sorted() 与基于 size 的 Comparator。
本文介绍如何将 java 中通过 collectors.groupingby 分组得到的 collection> 按各子列表元素数量从多到少排序,核心是结合 stream.sorted() 与基于 size 的 comparator。
在使用 Collectors.groupingBy 对集合进行分组后(例如按部门对人员分组),其返回值为 Map> —— 这是一个无序集合,不保证任何顺序。若需按每个部门人数(即每个 List
最简洁、推荐的方式是链式调用 Stream API:先获取分组后的 values,再转为流、排序、收集为有序列表(如 List>):
List<List<Person>> personsByDepartment = persons.stream()
.collect(Collectors.groupingBy(Person::getDepartment))
.values()
.stream()
.sorted(Comparator.<List<Person>>comparingInt(List::size).reversed())
.collect(Collectors.toList());✅ 关键点解析:
- Comparator.
- >comparingInt(List::size) 明确指定泛型类型,避免类型推断失败;
- .reversed() 表达“降序”意图清晰、语义直观,比手动写 (l1, l2) -> Integer.compare(l2.size(), l1.size()) 更安全、可读性更强;
- 最终结果为 List
- >(而非原始的 Collection),具备索引访问与确定顺序,便于后续遍历或取 Top-K。
⚠️ 注意事项:
立即学习“Java免费学习笔记(深入)”;
- 原始 groupingBy 不保留插入顺序(除非显式使用 LinkedHashMap),但此处排序逻辑完全独立于插入顺序,无需额外干预;
- 若输入 persons 为空,上述代码仍安全执行,返回空列表;
- 如需稳定排序(即人数相同时保持原始分组插入顺序),可叠加 .thenComparing(...),但通常部门间无天然次序,此需求较少;
- 避免在 .values() 后直接调用 Collections.sort(...) —— 因 Collection 不一定支持随机访问或可变操作(如 HashSet 返回的 Collection 不支持 sort)。
总结:排序的本质是对 List 的 size() 属性建模比较逻辑,而 Comparator.comparingInt(List::size).reversed() 是兼具表达力、类型安全与 JDK 兼容性的最佳实践。掌握该模式,可轻松扩展至按平均年龄、最大薪资等聚合指标排序。










