Java中Collectors.groupingBy实现多级分组本质是嵌套调用,每级对应一个分类条件,生成嵌套Map结构;支持两级、三级及以上分组,并可混用counting、summingDouble、mapping等下游收集器,还可指定TreeMap保证有序及处理null值。

Java 中用 Collectors.groupingBy 实现多级分组,本质是嵌套调用 groupingBy,每级对应一个分类条件,最终生成嵌套的 Map 结构(如 Map)。
两级分组:按部门再按职级分组
假设有一个员工列表,需先按 department 分组,再在每个部门内按 level 分组:
Map<string map list>>> grouped = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment, // 第一级:部门
Collectors.groupingBy(Employee::getLevel) // 第二级:职级
));</string>
结果是一个 Map,例如:{"研发": {"初级": [e1], "高级": [e2, e3]}, "测试": {"中级": [e4]}}
三级及以上分组:继续嵌套下游收集器
要加第三级(如按是否为正式员工 isFullTime),只需再嵌一层 groupingBy:
Map<string map list>>>> grouped3 = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.groupingBy(
Employee::getLevel,
Collectors.groupingBy(Employee::isFullTime)
)
));</string>
注意层级越深,返回类型越复杂,建议配合类型推导或显式声明变量类型,避免编译错误。
配合其他下游收集器增强实用性
多级分组不只能套 groupingBy,还可混用 counting、summingInt、mapping 等:
- 统计每个部门-职级组合下的人数:
Collectors.groupingBy(e -> e.getDepartment(),<br> Collectors.groupingBy(e -> e.getLevel(),<br> Collectors.counting()))
- 汇总每个部门-职级的薪资总和:
Collectors.groupingBy(Employee::getDepartment,<br> Collectors.groupingBy(Employee::getLevel,<br> Collectors.summingDouble(Employee::getSalary)))
- 只提取姓名字符串列表(避免暴露完整对象):
Collectors.groupingBy(Employee::getDepartment,<br> Collectors.groupingBy(Employee::getLevel,<br> Collectors.mapping(Employee::getName, Collectors.toList())))
自定义 Map 类型与空值处理
默认使用 HashMap,如需有序结果,可指定 TreeMap;同时建议处理可能的 null 字段,避免 NullPointerException:
Map<string map list>>> grouped = employees.stream()
.filter(e -> e.getDepartment() != null && e.getLevel() != null)
.collect(Collectors.groupingBy(
Employee::getDepartment,
TreeMap::new, // 使用 TreeMap 保证键有序
Collectors.groupingBy(
Employee::getLevel,
TreeMap::new,
Collectors.toList()
)
));</string>
若字段可能为 null,也可用 Objects.toString() 或三元表达式兜底转换。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











