Java 8 lambda用于为每个部门选择最高薪资员工

时间:2016-03-16 16:03:59

标签: java lambda java-8

class Employee {
    public string department;
    public int salary;
}

List<Employee> allEmployees = ...

我需要有一个列表,每个部门只有1名最高薪员工。 allEmployees是源列表。

4 个答案:

答案 0 :(得分:10)

您可以使用分组收集器执行此操作:

Map<String, Employee> topEmployees =
    allEmployees.stream()
                .collect(groupingBy(
                    e -> e.department,
                    collectingAndThen(maxBy(comparingInt(e -> e.salary)), Optional::get) 
                ));

使用静态导入

import static java.util.Comparator.comparingInt;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.maxBy;

此代码创建了Stream所有员工,并在Collectors.groupingBy的帮助下将他们与他们的部门分组。对于分类到相同密钥的所有值,我们只需要保留具有最大工资的员工,因此我们使用Collectors.maxBy收集它们,比较器将工资与Comparator.comparingInt进行比较。由于maxBy返回一个Optional<Employee>(为了处理列表为空的情况),我们用Collectors.collectingAndThen调用一个只返回员工的终结器来包装它:我们知道这种情况下,可选项不会为空。

答案 1 :(得分:5)

替代解决方案:

Map<String, Employee> topEmployees =
    allEmployees.stream()
            .collect(Collectors.toMap(
                e -> e.department,
                e -> e,
                BinaryOperator.maxBy(Comparator.comparingInt(e -> e.salary)) 
            ));

当我们遇到部门的第一位员工时,我们会向Map添加新条目。当找到另一名员工时,保留薪水较高的员工。这样你就不需要干涉选项。

答案 2 :(得分:1)

这不是诚实的解决方案。 由于信誉欠佳,我无法发表评论,这只是一个很小的发现,导致了这种纠正/改进。

我遇到了同样的情况,并尝试了上面提到的 Tagir Valeev's 解决方案,该解决方案对我来说很有效。 我在IDE中使用了它,但是由于编译器抱怨如下,所以返回的结果是错误的:

编译时错误:无法从Map<Object, Object>转换为Map<String, Employee>

这就是我了解此处的期望返回类型为Object类的类型,而不是我们期望的返回类型,即Map<String, Employee>

我只需要将我的结果接收到Map<Object, Object>中,而不是Map<String, Employee>

因此,以下代码重复了Map<Object, Object> topEmployees并将最终的预期结果存储到Map<String, Employee> finalResult;

Tagir Valeev的解决方案如下,我在接收端进行了调整:

Map<Object, Object> topEmployees = empList.stream()
            .collect(Collectors.groupingBy(e -> e.department, 
                    Collectors.collectingAndThen(
                            Collectors.maxBy(Comparator.comparingDouble(e -> e.salary)), Optional::get
                                                )
                                )
            );

我写的额外代码如下:

for(Map.Entry<Object, Object> token : topEmployees.entrySet()) {
        finalResult.put((String) token.getKey() , (Employee) token.getValue());
    }

希望这对某人有帮助。谢谢。

答案 3 :(得分:1)

/ 假设您有一个雇员列表作为List employeeList; 要首先找到部门薪水,您需要为员工配备比较器 /

Comparator<Employee> bySalary = Comparator.comparing(Employee::getSalary);

然后找到部门明智的最高薪金

Map<String, Optional<Employee>> collect = 
        employeeList.stream().collect(
            Collectors.groupingBy(
                Employee::getDept,
                Collectors.reducing(BinaryOperator.maxBy(bySalary))
    )
);

我们在这里做什么,  我们根据那里的部门对员工进行分组。  连同分组,我们是说还给我该部门的最高薪水, 最后只选择最大一个。 要查看Employee类中的输出覆盖toString方法并执行* /

collect.entrySet().stream().forEach(System.out::println);