【发布时间】:2016-07-02 15:27:07
【问题描述】:
class Employee {
public string department;
public int salary;
}
List<Employee> allEmployees = ...
我需要一个列表,每个部门只有 1 名最高薪员工。 allEmployees 是源列表。
【问题讨论】:
class Employee {
public string department;
public int salary;
}
List<Employee> allEmployees = ...
我需要一个列表,每个部门只有 1 名最高薪员工。 allEmployees 是源列表。
【问题讨论】:
您可以使用分组收集器来做到这一点:
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 来包装它,并使用一个只返回员工的finisher:我们知道在这种情况下可选的赢了不要为空。
【讨论】:
替代解决方案:
Map<String, Employee> topEmployees =
allEmployees.stream()
.collect(Collectors.toMap(
e -> e.department,
e -> e,
BinaryOperator.maxBy(Comparator.comparingInt(e -> e.salary))
));
当我们遇到该部门的第一个员工时,我们向Map 添加一个新条目。当找到另一名员工时,将保留一名薪水较高的员工。这样你就不需要干预可选了。
【讨论】:
/假设您有一个员工列表作为 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);
【讨论】:
老实说,这不是一个解决方案。 由于声誉低下,我无法发表评论,这只是一个很小的观察,导致了这种更正/即兴创作。
我遇到了同样的情况,我尝试了上述对我有用的 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());
}
希望这对某人有所帮助。谢谢。
【讨论】:
Map
【讨论】: