Collectors.groupingBy()是Java Stream API中用于按属性分组的核心工具,支持基础分组、分类+汇总(如计数、求和、平均值)、多级嵌套分组及空值处理。

在 Java 中,Collectors.groupingBy() 是 Stream API 提供的最常用分组工具之一,能快速按对象某个属性将列表划分为多个子集合,并支持进一步聚合(如求和、计数、平均值等)。关键在于理解其三个重载版本的适用场景,以及如何组合下游收集器实现“分类+汇总”。
基础分组:按单个属性生成 Map>
这是最常见用法,适用于简单归类。假设有一个员工列表,需按部门分组:
List<employee> employees = Arrays.asList(
new Employee("张三", "研发部", 15000),
new Employee("李四", "销售部", 8000),
new Employee("王五", "研发部", 18000)
);
Map<string list>> byDept = employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));
// 结果:{"研发部": [张三, 王五], "销售部": [李四]}
</string></employee>
分类 + 汇总:用下游收集器计算统计值
真正体现“汇总”能力的地方。通过第二个参数传入下游收集器,可直接得到每组的统计结果,避免后续遍历:
-
统计每组数量:
Collectors.counting() -
求每组薪资总和:
Collectors.summingDouble(Employee::getSalary) -
计算每组平均薪资:
Collectors.averagingDouble(Employee::getSalary) -
获取每组最高/最低薪资员工:
Collectors.maxBy(Comparator.comparing(Employee::getSalary))
示例:按部门汇总总薪资
Map<string double> deptSalarySum = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.summingDouble(Employee::getSalary)
));
// 结果:{"研发部": 33000.0, "销售部": 8000.0}
</string>
多级分组与嵌套汇总
当需要按多个维度分组(如“先按部门,再按职级”),可嵌套使用 groupingBy:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
Map<string map long>> deptAndLevelCount = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.groupingBy(
Employee::getLevel,
Collectors.counting()
)
));
// 结果:{"研发部": {"高级": 2}, "销售部": {"中级": 1}}
</string>
注意:内层 groupingBy 作为下游收集器,返回的是 Map<k2 v2></k2>,整体类型为 Map<k1 map v2>></k1>。
处理空值与自定义分组键
若分组属性可能为 null,默认会抛 NullPointerException。可借助 Function.identity() 或自定义映射函数规避:
- 用
Objects.toString(emp.getDepartment(), "未知")将 null 转为默认值 - 使用
Collectors.groupingBy(emp -> emp.getDepartment() != null ? emp.getDepartment() : "未分配") - 若需保持插入顺序,可指定 map 工厂:
Collectors.groupingBy(..., LinkedHashMap::new, ...)
不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










