如何使用Java Stream API对Employee列表按部门公共属性分组聚合
实现步骤
你需要先定义2个DTO类来承接聚合后的结构,再通过Stream API的分组能力完成转换:
- 定义员工个人信息DTO,仅保留员工私有属性
- 定义部门聚合DTO,包含部门公共属性 + 对应员工列表
- 用Stream的
groupingBy按部门唯一标识分组,再把每个分组转换为部门聚合DTO
代码实现
第一步:定义DTO类
如果你的项目用了Lombok,直接给类加@Data注解即可省略getter/setter代码,没有的话自行补充对应属性的get、set方法。
// 员工个人信息DTO class EmployeeInfo { private String firstName; private String lastName; private Long salary; private int experience; // 直接从原Employee对象转换属性 public EmployeeInfo(Employee employee) { this.firstName = employee.getFirstName(); this.lastName = employee.getLastName(); this.salary = employee.getSalary(); this.experience = employee.getExperience(); } } // 部门聚合DTO class DepartmentAgg { private String department; private String departmentId; private int floor; private Boolean isBonusApplicable; private List<EmployeeInfo> employees; // 从同组员工取公共属性 + 员工列表初始化 public DepartmentAgg(Employee deptAttr, List<EmployeeInfo> employees) { this.department = deptAttr.getDepartment(); this.departmentId = deptAttr.getDepartmentId(); this.floor = deptAttr.getFloor(); this.isBonusApplicable = deptAttr.getIsBonusApplicable(); this.employees = employees; } } // 最外层结果包装类,对应你要的输出结构 class ResultWrapper { private List<DepartmentAgg> department; public List<DepartmentAgg> getDepartment() { return department; } public void setDepartment(List<DepartmentAgg> department) { this.department = department; } }
第二步:Stream核心处理逻辑
import java.util.stream.Collectors; // 你原有获取员工列表的代码 List<Employee> employeeList = dao.getEmployeeList(); // 分组聚合逻辑 List<DepartmentAgg> deptAggList = employeeList.stream() // 按部门ID分组,同部门的员工会被分到同一组 .collect(Collectors.groupingBy(Employee::getDepartmentId)) // 遍历所有分组,转换为部门聚合DTO .values() .stream() .map(sameDeptEmps -> { // 同部门的公共属性完全一致,取第一个员工的对应属性即可 Employee firstEmp = sameDeptEmps.get(0); // 把当前组的所有员工转换为员工个人信息DTO List<EmployeeInfo> empInfos = sameDeptEmps.stream() .map(EmployeeInfo::new) .collect(Collectors.toList()); return new DepartmentAgg(firstEmp, empInfos); }) .collect(Collectors.toList()); // 封装为最终输出结构 ResultWrapper result = new ResultWrapper(); result.setDepartment(deptAggList);
异常场景兼容
如果你担心存在部门ID相同但其他公共属性不一致的异常数据,可以把分组key换成包含所有部门公共属性的组合键,Java 16+可以用record快速定义:
// 部门组合键,自动重写equals和hashCode方法 record DeptKey(String department, String departmentId, int floor, Boolean isBonusApplicable) {} // 分组逻辑替换为按组合键分组即可 .collect(Collectors.groupingBy(emp -> new DeptKey(emp.getDepartment(), emp.getDepartmentId(), emp.getFloor(), emp.getIsBonusApplicable())))
低版本Java可以自定义Key类,手动重写equals和hashCode方法实现相同效果。
内容的提问来源于stack exchange,提问作者PDJ
相关产品推荐
相关产品推荐

