如何在Java流中使用MaxBy进行分组和聚合
我有一个如何在Java流中使用MaxBy进行分组和聚合,java,java-8,java-stream,Java,Java 8,Java Stream,我有一个Employee对象列表,如下所示 public class Employee { int eno; String name; String dept; int salary; ...... } 要求是获得每个部门最高工资的员工名单。部门中可以有多个员工拥有相同的最高工资。例如,销售团队可能有两名员工,比如Alex&John,他们的工资最高 List<Employee> eList = new ArrayList<>();
Employee
对象列表,如下所示
public class Employee {
int eno;
String name;
String dept;
int salary;
......
}
要求是获得每个部门最高工资的员工名单。部门中可以有多个员工拥有相同的最高工资。例如,销售团队可能有两名员工,比如Alex&John,他们的工资最高
List<Employee> eList = new ArrayList<>();
eList .add(new Employee(101, "ALEX","SALES",7000));
eList.add(new Employee(102, "KATHY","ADMIN",3000));
eList.add(new Employee(103, "JOHN","SALES",7000));
eList.add(new Employee(104, "KONG","IT",5000));
eList.add(new Employee(105, "MIKE","SALES",4000));
List eList=new ArrayList();
添加列表(新员工(101,“ALEX”,“SALES”,7000);
eList.add(新员工(102,“KATHY”,“ADMIN”,3000));
eList.add(新员工(103,“JOHN”,“SALES”,7000));
添加(新员工(104,“香港”,“IT”,5000));
eList.add(新员工(105,“迈克”,“销售”,4000));
预期输出为->映射(部门,具有最高工资的姓名列表)
使用下面的代码,我只能得到一个Employee对象作为输出,即使有多个Employee满足该条件
Map<String, Employee> maxSalEmpNameByDept = eList.stream().collect(groupingBy(Employee::getDept,
collectingAndThen(maxBy(Comparator.comparing(Employee::getSalary)), Optional::get)));
Map maxSalEmpNameByDept=eList.stream().collect(groupingBy(Employee::getDept,
collectingAndThen(maxBy(Comparator.comparing(Employee::getSalary)),可选::get));
这是因为MaxBy方法在找到满足给定条件的第一项时停止
Map<String, Employee> maxSalEmpNameByDept = eList.stream().collect(groupingBy(Employee::getDept,
collectingAndThen(maxBy(Comparator.comparing(Employee::getSalary)), Optional::get)));
我的问题是:
Map
)Map
)首先,使用
Collectors.toMap
Map<String, Integer> maxSalByDept =
eList.stream()
.collect(Collectors.toMap(Employee::getDept, Employee::getSalary,
BinaryOperator.maxBy(Comparator.comparing(Function.identity()))));
首先,使用
Collectors.toMap
Map<String, Integer> maxSalByDept =
eList.stream()
.collect(Collectors.toMap(Employee::getDept, Employee::getSalary,
BinaryOperator.maxBy(Comparator.comparing(Function.identity()))));
如果你写自己的收藏家,这很容易。我在真正搜索之前写过这篇文章,但图书馆实际上已经有了
如果你写自己的收藏家,这很容易。我在真正搜索之前写过这篇文章,但图书馆实际上已经有了
这里有一种方法不使用显式的
比较器
或某些第三方库。我填写了你的Employee类并添加了一些额外的员工
提供的数据
List<Employee> eList = new ArrayList<>();
eList.add(new Employee(101, "ALEX", "SALES", 7000));
eList.add(new Employee(102, "KATHY", "ADMIN", 3000));
eList.add(new Employee(103, "JOHN", "SALES", 7000));
eList.add(new Employee(104, "KONG", "IT", 5000));
eList.add(new Employee(106, "MIKE", "SALES", 4000));
eList.add(new Employee(107, "BOB", "IT", 4000));
eList.add(new Employee(108, "SARAH", "ADMIN", 2000));
eList.add(new Employee(109, "RALPH", "SALES", 4000));
eList.add(new Employee(110, "JUNE", "ADMIN", 3000));
印刷品
ADMIN=[{102, KATHY, ADMIN, 3000}, {110, JUNE, ADMIN, 3000}]
IT=[{104, KONG, IT, 5000}]
SALES=[{101, ALEX, SALES, 7000}, {103, JOHN, SALES, 7000}]
IT=[KONG]
ADMIN=[KATHY, JUNE]
SALES=[ALEX, JOHN]
要仅获取名称,请使用刚刚创建的地图
- 流化值(员工列表)
- 然后通过flatMap将员工列表放入一个
流中Employee
- 记住,在这一点上,这是每个部门的最高工资,所以 只需按部门对员工进行分组,并将他们的姓名收集到一个列表中
public static class Employee {
private int eno;
private String name;
private String dept;
private int salary;
public Employee(int eno, String name, String dept,
int salary) {
this.eno = eno;
this.name = name;
this.dept = dept;
this.salary = salary;
}
public int getEno() {
return eno;
}
public String getName() {
return name;
}
public String getDept() {
return dept;
}
public int getSalary() {
return salary;
}
@Override
public String toString() {
return String.format("{%s, %s, %s, %s}", eno, name,
dept, salary);
}
}
}
这里有一种方法不使用显式的
比较器
或某些第三方库。我填写了你的Employee类并添加了一些额外的员工
提供的数据
List<Employee> eList = new ArrayList<>();
eList.add(new Employee(101, "ALEX", "SALES", 7000));
eList.add(new Employee(102, "KATHY", "ADMIN", 3000));
eList.add(new Employee(103, "JOHN", "SALES", 7000));
eList.add(new Employee(104, "KONG", "IT", 5000));
eList.add(new Employee(106, "MIKE", "SALES", 4000));
eList.add(new Employee(107, "BOB", "IT", 4000));
eList.add(new Employee(108, "SARAH", "ADMIN", 2000));
eList.add(new Employee(109, "RALPH", "SALES", 4000));
eList.add(new Employee(110, "JUNE", "ADMIN", 3000));
印刷品
ADMIN=[{102, KATHY, ADMIN, 3000}, {110, JUNE, ADMIN, 3000}]
IT=[{104, KONG, IT, 5000}]
SALES=[{101, ALEX, SALES, 7000}, {103, JOHN, SALES, 7000}]
IT=[KONG]
ADMIN=[KATHY, JUNE]
SALES=[ALEX, JOHN]
要仅获取名称,请使用刚刚创建的地图
- 流化值(员工列表)
- 然后通过flatMap将员工列表放入一个
流中Employee
- 记住,在这一点上,这是每个部门的最高工资,所以 只需按部门对员工进行分组,并将他们的姓名收集到一个列表中
public static class Employee {
private int eno;
private String name;
private String dept;
private int salary;
public Employee(int eno, String name, String dept,
int salary) {
this.eno = eno;
this.name = name;
this.dept = dept;
this.salary = salary;
}
public int getEno() {
return eno;
}
public String getName() {
return name;
}
public String getDept() {
return dept;
}
public int getSalary() {
return salary;
}
@Override
public String toString() {
return String.format("{%s, %s, %s, %s}", eno, name,
dept, salary);
}
}
}
嵌套分组后,可以通过这种方式避免flatMaping
…entrySet().stream().collect(Collectors.toMap(m->m.getKey(),m->m.getValue().lastEntry().getValue())代码>@Rono观察力极佳。我做了改变。谢谢嵌套分组后,可以通过这种方式避免flatMaping…entrySet().stream().collect(Collectors.toMap(m->m.getKey(),m->m.getValue().lastEntry().getValue())代码>@Rono观察力极佳。我做了改变。谢谢具有完整的收集器,因此无需考虑是否添加合并函数。有一个完整的收集器,因此无需考虑是否添加合并功能。@Holger我想这个问题部分解决了这个问题,因为OP需要每个部门的最高工资员工名单。@Rono给出OP的原始代码,在我看来,对流API有足够的理解,可以组合一个收集器,如对groupingBy
链接问题的第二个答案所示。否则,他们可能会提出一个新问题。@Holger我认为这个问题部分解决了这个问题,因为OP需要每个部门的最高工资员工名单。@Rono鉴于OP的原始代码,在我看来,对Stream API有足够的了解,可以合并一个收集器,如groupingBy
链接问题的第二个答案所示。否则,他们可能会提出一个新问题。
public static class Employee {
private int eno;
private String name;
private String dept;
private int salary;
public Employee(int eno, String name, String dept,
int salary) {
this.eno = eno;
this.name = name;
this.dept = dept;
this.salary = salary;
}
public int getEno() {
return eno;
}
public String getName() {
return name;
}
public String getDept() {
return dept;
}
public int getSalary() {
return salary;
}
@Override
public String toString() {
return String.format("{%s, %s, %s, %s}", eno, name,
dept, salary);
}
}
}