使用Java 8 Stream获取各部门薪资第二高的员工
按部门获取薪资第二高的员工实现方案
核心思路
先按部门对员工分组,再对每个部门的员工集合按薪资降序排序,跳过薪资最高的第一个员工后,取第一个结果就是该部门薪资第二高的员工。同时要处理部门员工数不足2人的边界情况,避免空指针异常。
实现代码(保留同薪资员工的场景)
如果需要保留同薪资的员工(即部门内有多个最高薪员工时,第二高可以是同薪资的另一位员工),可以用以下代码:
import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; public class EmployeeDemo { public static void main(String[] args) { List<Employee> employeeList = List.of( new Employee(10000L, "技术部"), new Employee(20000L, "技术部"), new Employee(20000L, "技术部"), new Employee(15000L, "技术部"), new Employee(25000L, "市场部"), new Employee(22000L, "市场部"), new Employee(30000L, "人事部") ); Map<String, Optional<Employee>> secondHighestByDept = employeeList.stream() .collect(Collectors.groupingBy( Employee::getDepartment, Collectors.collectingAndThen( Collectors.toList(), empList -> empList.stream() .sorted(Comparator.comparingLong(Employee::getSalary).reversed()) .skip(1) .findFirst() ) )); // 输出结果 secondHighestByDept.forEach((dept, empOpt) -> { System.out.printf("部门:%s - ", dept); empOpt.ifPresentOrElse( emp -> System.out.printf("薪资第二高的员工薪资:%d%n", emp.getSalary()), () -> System.out.println("无薪资第二高的员工") ); }); } } class Employee { private Long salary; private String department; public Employee(Long salary, String department) { this.salary = salary; this.department = department; } public Long getSalary() { return salary; } public String getDepartment() { return department; } }
实现代码(严格取薪资第二高的场景)
如果需要严格获取薪资低于最高薪的员工(即排除同薪资的最高薪员工),可以用TreeSet自动排序并去重薪资:
import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.TreeSet; import java.util.stream.Collectors; public class EmployeeDemo { public static void main(String[] args) { List<Employee> employeeList = List.of( new Employee(10000L, "技术部"), new Employee(20000L, "技术部"), new Employee(20000L, "技术部"), new Employee(15000L, "技术部"), new Employee(25000L, "市场部"), new Employee(22000L, "市场部"), new Employee(30000L, "人事部") ); Map<String, Optional<Employee>> secondHighestByDept = employeeList.stream() .collect(Collectors.groupingBy( Employee::getDepartment, Collectors.collectingAndThen( // 用TreeSet按薪资降序排序,自动去重同薪资的员工 Collectors.toCollection(() -> new TreeSet<>(Comparator.comparingLong(Employee::getSalary).reversed())), sortedSet -> { var iterator = sortedSet.iterator(); if (iterator.hasNext()) iterator.next(); // 跳过最高薪员工 return iterator.hasNext() ? Optional.of(iterator.next()) : Optional.empty(); } ) )); // 输出结果 secondHighestByDept.forEach((dept, empOpt) -> { System.out.printf("部门:%s - ", dept); empOpt.ifPresentOrElse( emp -> System.out.printf("薪资第二高的员工薪资:%d%n", emp.getSalary()), () -> System.out.println("无薪资第二高的员工") ); }); } } class Employee { private Long salary; private String department; public Employee(Long salary, String department) { this.salary = salary; this.department = department; } public Long getSalary() { return salary; } public String getDepartment() { return department; } }
关键说明
- 两种实现都用
Optional包装结果,避免部门只有1名员工时出现空指针。 - 第一种方案适合需要保留同薪资员工的场景,第二种方案适合需要严格区分薪资层级的场景。
内容的提问来源于stack exchange,提问作者JNRaj
相关产品推荐
相关产品推荐

