class Employee {
public string department;
public int salary;
}
List<Employee> allEmployees = ...
我需要有一个列表,每个部门只有1名最高薪员工。 allEmployees是源列表。
答案 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);