You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Java Stream API对Employee列表按部门公共属性分组聚合

实现步骤

你需要先定义2个DTO类来承接聚合后的结构,再通过Stream API的分组能力完成转换:

  1. 定义员工个人信息DTO,仅保留员工私有属性
  2. 定义部门聚合DTO,包含部门公共属性 + 对应员工列表
  3. 用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 13:24:09