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

如何在运行时根据属性值动态将Employee List拆分为List集合

按name、sal、joinDate动态分组Employee列表的方案

要实现不硬编码属性值、按name/sal/joinDate组合动态分组的需求,核心是利用Java Stream的Collectors.groupingBy,通过自定义分组键来匹配属性组合——只要两个Employee的这三个属性完全相等,就会被分到同一组。

第一步:完善Employee类

原Employee类缺少属性getter,必须添加才能在stream中获取分组所需的属性值:

import java.math.BigDecimal;
import java.util.Date;

public class Employee {
    private String name;
    private long id;
    private BigDecimal sal;
    private Date joinDate;

    public Employee(String name, long id, BigDecimal sal, Date date) {
        super();
        this.name = name;
        this.id = id;
        this.sal = sal;
        this.joinDate = date;
    }

    // 添加分组所需的getter
    public String getName() { return name; }
    public BigDecimal getSal() { return sal; }
    public Date getJoinDate() { return joinDate; }

    // 可选:重写toString方便查看结果
    @Override
    public String toString() {
        return "Employee{name='" + name + "', id=" + id + ", sal=" + sal + ", joinDate=" + joinDate + '}';
    }
}

方案一:自定义分组键类(兼容Java 8+)

创建一个包含三个分组属性的GroupKey类,重写equals和hashCode——这是分组的核心依据,确保相同属性组合的键会被视为相等:

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.text.SimpleDateFormat;
import java.util.stream.Collectors;

class GroupKey {
    private final String name;
    private final BigDecimal sal;
    private final Date joinDate;

    public GroupKey(String name, BigDecimal sal, Date joinDate) {
        this.name = name;
        this.sal = sal;
        this.joinDate = joinDate;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        GroupKey groupKey = (GroupKey) o;
        return name.equals(groupKey.name) && sal.equals(groupKey.sal) && joinDate.equals(groupKey.joinDate);
    }

    @Override
    public int hashCode() {
        int result = name.hashCode();
        result = 31 * result + sal.hashCode();
        result = 31 * result + joinDate.hashCode();
        return result;
    }
}

public class EmployeeGroupingDemo {
    public static void main(String[] args) throws Exception {
        List<Employee> employeeList = new ArrayList<>();
        // 注意用yyyy表示年,避免YYYY(周年)的解析问题
        SimpleDateFormat format = new SimpleDateFormat("MMddyyyy");

        employeeList.add(new Employee("Mike", 1000, BigDecimal.valueOf(200), format.parse("08122022")));
        employeeList.add(new Employee("David", 1001, BigDecimal.valueOf(100), format.parse("08112022")));
        employeeList.add(new Employee("Mike", 1002, BigDecimal.valueOf(200), format.parse("08122022")));
        employeeList.add(new Employee("David", 1003, BigDecimal.valueOf(100), format.parse("08112022")));
        employeeList.add(new Employee("David", 1003, BigDecimal.valueOf(200), format.parse("08112022")));
        employeeList.add(new Employee("David", 1003, BigDecimal.valueOf(200), format.parse("08122022")));

        // 核心分组逻辑:用GroupKey作为分组依据
        Map<GroupKey, List<Employee>> groupedMap = employeeList.stream()
                .collect(Collectors.groupingBy(emp -> new GroupKey(emp.getName(), emp.getSal(), emp.getJoinDate())));

        // 将Map的value转换为需求的List<List<Employee>>
        List<List<Employee>> result = new ArrayList<>(groupedMap.values());

        // 打印验证分组结果
        int groupNum = 1;
        for (List<Employee> group : result) {
            System.out.println("第" + groupNum + "组:");
            group.forEach(System.out::println);
            groupNum++;
        }
    }
}

方案二:用Java 16+ Record简化代码

Java 16引入的Record会自动生成equals、hashCode和toString,可以大幅简化分组键的编写:

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.text.SimpleDateFormat;
import java.util.stream.Collectors;

// Record自动实现equals和hashCode,直接作为分组键
record GroupKey(String name, BigDecimal sal, Date joinDate) {}

public class EmployeeGroupingDemo {
    public static void main(String[] args) throws Exception {
        List<Employee> employeeList = new ArrayList<>();
        SimpleDateFormat format = new SimpleDateFormat("MMddyyyy");

        employeeList.add(new Employee("Mike", 1000, BigDecimal.valueOf(200), format.parse("08122022")));
        employeeList.add(new Employee("David", 1001, BigDecimal.valueOf(100), format.parse("08112022")));
        employeeList.add(new Employee("Mike", 1002, BigDecimal.valueOf(200), format.parse("08122022")));
        employeeList.add(new Employee("David", 1003, BigDecimal.valueOf(100), format.parse("08112022")));
        employeeList.add(new Employee("David", 1003, BigDecimal.valueOf(200), format.parse("08112022")));
        employeeList.add(new Employee("David", 1003, BigDecimal.valueOf(200), format.parse("08122022")));

        // 分组逻辑更简洁
        Map<GroupKey, List<Employee>> groupedMap = employeeList.stream()
                .collect(Collectors.groupingBy(emp -> new GroupKey(emp.getName(), emp.getSal(), emp.getJoinDate())));

        List<List<Employee>> result = new ArrayList<>(groupedMap.values());

        // 打印结果
        int groupNum = 1;
        for (List<Employee> group : result) {
            System.out.println("第" + groupNum + "组:");
            group.forEach(System.out::println);
            groupNum++;
        }
    }
}

关键说明

  • Collectors.groupingBy会根据提供的键提取器,自动将属性组合相同的Employee分到同一组,无需硬编码任何属性值。
  • BigDecimal和Date都正确实现了equals和hashCode,可以直接作为分组键的属性。
  • 运行上述代码,示例中的6个Employee会被分成4组(与你提到的3组可能存在示例数据描述误差),完全符合动态分组的需求。

内容的提问来源于stack exchange,提问作者chaitu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 06:55:24