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

如何对Employee列表按部门和性别分组,筛选每组最高薪资员工?

问题:获取各部门各性别薪资最高的员工

给定的对象结构与员工列表

我们有如下Employee类定义:

public class Employee {
    private String name;
    private String department;
    private String gender;
    private String designation;
    private Integer salary;

    // 需提供构造方法、getter方法(示例中用到的getDepartment、getGender、getSalary必须实现)
    public Employee(String name, String department, String gender, String designation, Integer salary) {
        this.name = name;
        this.department = department;
        this.gender = gender;
        this.designation = designation;
        this.salary = salary;
    }

    public String getDepartment() { return department; }
    public String getGender() { return gender; }
    public Integer getSalary() { return salary; }
    public String getName() { return name; }
    public String getDesignation() { return designation; }

    // 重写toString方便输出结果
    @Override
    public String toString() {
        return String.format("Employee(\"%s\", \"%s\", \"%s\", \"%s\", %d)",
                name, department, gender, designation, salary);
    }
}

对应的员工列表:

List<Employee> listEmployees = new ArrayList<>(List.of(
    new Employee("Mark", "Marketing", "male", "Sales Manager", 9200),
    new Employee("Tom", "Marketing", "male", "Sales Manager", 2800),
    new Employee("Travis", "Marketing", "male", "Sales Manager", 3850),
    new Employee("Diana", "Marketing", "female", "Sales Manager", 1900),
    new Employee("Keith", "R&D", "male", "Software Engineer", 4000),
    new Employee("Liam", "R&D", "male", "Software Engineer", 5200),
    new Employee("Whitney", "R&D", "female", "Software Engineer", 6000),
    new Employee("Tina", "R&D", "female", "Software Engineer", 7500),
    new Employee("Patrick", "Government", "female", "Service", 7100),
    new Employee("Luc", "Government", "male", "Service", 3300),
    new Employee("Philippe", "Government", "female", "Service", 2800),
    new Employee("David", "Government", "female", "Service", 4700)
));

需求说明

需要从员工列表中筛选出每个部门、每个性别下薪资最高的员工,期望结果如下:

Employee("Mark", "Marketing", "male", "Sales Manager", 9200)
Employee("Diana", "Marketing", "female", "Sales Manager", 1900)
Employee("Liam", "R&D", "male", "Software Engineer", 5200)
Employee("Tina", "R&D", "female", "Software Engineer", 7500)
Employee("Patrick", "Government", "female", "Service", 7100)
Employee("Luc", "Government", "male", "Service", 3300)

当前尝试的代码

已经实现了按部门和性别的两层分组,但不知道如何进一步筛选每组的最高薪资员工:

listEmployees.stream()
    .collect(Collectors.groupingBy(Employee::getDepartment, Collectors.groupingBy(Employee::getGender)));

解决方案

方案1:嵌套分组结合maxBy筛选

在嵌套分组的基础上,为每个性别分组添加maxBy收集器,获取该组薪资最高的员工,再通过collectingAndThen处理Optional结果:

List<Employee> topEmployees = listEmployees.stream()
    // 外层按部门分组,内层按性别分组,每组取薪资最高的员工
    .collect(Collectors.groupingBy(Employee::getDepartment,
             Collectors.groupingBy(Employee::getGender,
             Collectors.collectingAndThen(
                 Collectors.maxBy(Comparator.comparingInt(Employee::getSalary)),
                 Optional::get))))
    // 展开嵌套的Map结构,提取所有员工
    .values().stream()
    .flatMap(deptGroup -> deptGroup.values().stream())
    .collect(Collectors.toList());

// 输出结果
topEmployees.forEach(System.out::println);

方案2:使用复合分组键(更简洁)

用部门+性别作为复合分组键,直接按组合条件分组后筛选每组最高薪资员工:

Java 16+ 可用Record作为复合键

// 定义复合分组键
record DeptGender(String department, String gender) {}

List<Employee> topEmployees = listEmployees.stream()
    .collect(Collectors.groupingBy(
        emp -> new DeptGender(emp.getDepartment(), emp.getGender()),
        Collectors.collectingAndThen(
            Collectors.maxBy(Comparator.comparingInt(Employee::getSalary)),
            Optional::get)))
    .values().stream()
    .collect(Collectors.toList());

兼容低版本Java(用SimpleEntry)

如果无法使用Record,可借助AbstractMap.SimpleEntry作为复合键:

List<Employee> topEmployees = listEmployees.stream()
    .collect(Collectors.groupingBy(
        emp -> new AbstractMap.SimpleEntry<>(emp.getDepartment(), emp.getGender()),
        Collectors.collectingAndThen(
            Collectors.maxBy(Comparator.comparingInt(Employee::getSalary)),
            Optional::get)))
    .values().stream()
    .collect(Collectors.toList());

代码说明

  • Collectors.maxBy(Comparator.comparingInt(Employee::getSalary)):按薪资升序比较,返回该组薪资最高的员工(封装在Optional中)
  • Collectors.collectingAndThen(...):将Optional转换为实际的Employee对象(需确保每组至少有一个员工,这里的数据源满足该条件)
  • 最后通过values()和flatMap将嵌套的Map结构展开为List<Employee>,得到最终结果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 15:35:52