
使用 java 8 stream 的 groupingby 与 summingdouble 收集器,可高效地按员工 id 分组、合并同 id 的 compensation 值,并重建 employee 对象列表。
使用 java 8 stream 的 groupingby 与 summingdouble 收集器,可高效地按员工 id 分组、合并同 id 的 compensation 值,并重建 employee 对象列表。
在实际业务中(如薪资结算、报表汇总),常需对具有相同标识(如 id)的自定义对象进行去重与数值聚合。针对 Employee 类型列表,目标是:保留唯一 id,同时将其所有对应 compensation 值累加。Java 8 的 Stream API 提供了简洁、函数式且线程安全的解决方案。
核心思路分三步:
- 按 id 分组 → 使用 Collectors.groupingBy(Employee::getId, ...);
-
聚合 compensation → 嵌套 Collectors.summingDouble(Employee::getCompensation),自动返回 Map
; - 重构为 Employee 列表 → 遍历 entrySet(),用每个键值对构造新 Employee(id, sum)。
以下是完整可运行示例:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
import java.util.*;
import java.util.stream.Collectors;
class Employee {
private final String id;
private final float compensation; // 建议设为 final,保证不可变性
public Employee(String id, float compensation) {
this.id = Objects.requireNonNull(id);
this.compensation = compensation;
}
public String getId() { return id; }
public float getCompensation() { return compensation; }
@Override
public String toString() {
return "Employee{id='" + id + "', compensation=" + compensation + "}";
}
}
public class EmployeeAggregator {
public static List<employee> aggregateById(List<employee> employees) {
if (employees == null) {
return Collections.emptyList();
}
return employees.stream()
.collect(Collectors.groupingBy(
Employee::getId,
Collectors.summingDouble(Employee::getCompensation)
))
.entrySet().stream()
.map(entry -> new Employee(entry.getKey(), entry.getValue().floatValue()))
.collect(Collectors.toList());
}
// 测试用例
public static void main(String[] args) {
List<employee> payment = Arrays.asList(
new Employee("1", 3000.00f),
new Employee("1", 6000.00f),
new Employee("2", 5000.00f),
new Employee("3", 4000.00f)
);
List<employee> aggregated = aggregateById(payment);
aggregated.forEach(System.out::println);
// 输出:
// Employee{id='1', compensation=9000.0}
// Employee{id='2', compensation=5000.0}
// Employee{id='3', compensation=4000.0}
}
}</employee></employee></employee></employee>
✅ 注意事项:
- summingDouble 返回 double,需显式转为 float(.floatValue()),避免精度隐式丢失;若对精度敏感(如金融场景),建议将 compensation 改为 BigDecimal 并使用 Collectors.collectingAndThen 配合 BigDecimal::add;
- Employee 的 compensation 字段建议设为 final,增强不可变性与线程安全性;
- 若输入列表可能为 null,应在方法开头做空值防护(如示例中所示);
- 此方案时间复杂度为 O(n),优于嵌套循环的 O(n²),且代码可读性强、易于维护。
该模式可轻松泛化至其他实体类(如 Product 按 SKU 合计库存、Order 按用户 ID 汇总金额),是 Java 函数式数据处理的典型实践。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










