class Employee {
public string department;
public int salary;
}
List<Employee> allEmployees = ...
I need to have a list that will have only 1 top salary employee for each department. allEmployees is the source list.
class Employee {
public string department;
public int salary;
}
List<Employee> allEmployees = ...
I need to have a list that will have only 1 top salary employee for each department. allEmployees is the source list.
You can do that with a grouping collector:
Map<String, Employee> topEmployees =
allEmployees.stream()
.collect(groupingBy(
e -> e.department,
collectingAndThen(maxBy(comparingInt(e -> e.salary)), Optional::get)
));
with the static imports
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;
This code creates a Stream
of all the employees and groups them with their department with the help of Collectors.groupingBy
. For all the values classified to the same key, we need to keep only the employee with the maximum salary, so we collect them with Collectors.maxBy
and the comparator compares the salary with Comparator.comparingInt
. Since maxBy
returns an Optional<Employee>
(to handle the case where there the list is empty), we wrap it with a call to Collectors.collectingAndThen
with a finisher that just returns the employee: we know in this case that the optional won't be empty.
Alternative solution:
Map<String, Employee> topEmployees =
allEmployees.stream()
.collect(Collectors.toMap(
e -> e.department,
e -> e,
BinaryOperator.maxBy(Comparator.comparingInt(e -> e.salary))
));
When we encounter the first employee from the department, we add a new entry to the Map
. When another employee is found, one with higher salary is kept. This way you don't need to meddle with optionals.
/Let's say you have a list of employee as List employeeList; To find the departmentwise salary first you need to have comparator for employees/
Comparator<Employee> bySalary = Comparator.comparing(Employee::getSalary);
Then to find departement wise highest salary you do
Map<String, Optional<Employee>> collect =
employeeList.stream().collect(
Collectors.groupingBy(
Employee::getDept,
Collectors.reducing(BinaryOperator.maxBy(bySalary))
)
);
What are we doing here is, we are grouping the employees on the basis of there department. And along with Grouping we are saying return me the highest salary taker for that department, And finally pick only max one. To see the output override toString method in Employee class and do */
collect.entrySet().stream().forEach(System.out::println);
This is not a solution honestly. Since I can't comment due to the low reputation, This is just a tiny observation which led to this correction/improvisation.
I ran into this same scenario & I tried Tagir Valeev's solution mentioned above which worked for me. I used it as it is in my IDE, But the returned result was erroneous as the compiler complained as follows:
Compile Time Error: cannot convert from Map<Object, Object>
to Map<String, Employee>
.
That's where I understood the expected return type here is of type class Object & not what we expect it to be i.e Map<String, Employee>
I simply had to receive the my result into Map<Object, Object>
instead of Map<String, Employee>
.
Hence the following code where Map<Object, Object> topEmployees
is iterated & the final expected result is stored into the Map<String, Employee> finalResult;
Tagir Valeev's solution is as below which I tweaked at receiving end:
Map<Object, Object> topEmployees = empList.stream()
.collect(Collectors.groupingBy(e -> e.department,
Collectors.collectingAndThen(
Collectors.maxBy(Comparator.comparingDouble(e -> e.salary)), Optional::get
)
)
);
The extra code I wrote is as below:
for(Map.Entry<Object, Object> token : topEmployees.entrySet()) {
finalResult.put((String) token.getKey() , (Employee) token.getValue());
}
Hope this helps someone. Thanks.
Map<String, Optional> result = li.stream().collect(Collectors.groupingBy(Emp::getDept, Collectors.reducing(BinaryOperator.maxBy(Comparator.comparing(Emp::getSalary))) ));
max salary in each department java 8
import java.util.*;
import java.util.stream.Collectors;
Map<String, Employee> stringEmployeeMap= employeeList.stream()
.collect(Collectors.groupingBy(Employee::getDepartment,
Collectors.collectingAndThen(
Collectors.maxBy(
Comparator.comparingDouble(Employee::getSalary)
), Optional::get)
)
);
import static java.util.Comparator.comparingDouble;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.maxBy;
empList.stream().collect(
groupingBy(e -> e.department,
collectingAndThen(maxBy(comparingDouble(e -> e.salary)),
Optional::get))).
forEach((k, v) -> System.out.println(k + ":" + v));
package com.example.demo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.el.stream.Optional;
import org.springframework.expression.spel.ast.OpAnd;
import org.springframework.util.comparator.Comparators;
public class Java8Test {
public static void main(String[] args) {
int[] arr = new int[] {3,98,4,1,3,5,7,9,8,7,6,55,44,33,22,34};
Arrays.stream(arr).filter(x->x%2==0).forEach(action -> {
System.out.println("Array event number : " +action);
});
List<Employee> empList = new ArrayList<Employee>();
empList.add(new Employee(101, "siva", 101, "active", 2000));
empList.add(new Employee(102, "ready", 101, "active", 5000));
empList.add(new Employee(103, "raju", 102, "inactive", 6000));
empList.add(new Employee(104, "sunder", 102, "inaactive", 4000));
empList.add(new Employee(105, "sunil", 103, "active", 3500));
empList.add(new Employee(106, "sunath", 103, "inactive", 4200));
empList.add(new Employee(107, "suresh", 104, "active", 2050));
Map<Integer, java.util.Optional<Employee>> mapMaxSalByDept= empList.stream().collect(Collectors.groupingBy(
Employee::getEmpDepId, Collectors.reducing(BinaryOperator.maxBy(Comparator.comparing(Employee::getEmpSalary)))));
mapMaxSalByDept.entrySet().forEach(action-> {
System.out.println("DEMP Id : " + action.getKey()+ "Empl Details : "+ action.getValue());
});
//nth max salary n=3
Stream<Employee> mapMaxSalByDept1Nth= empList.stream().sorted(Comparator.comparing(Employee:: getEmpSalary).reversed()).limit(3).skip(2);
mapMaxSalByDept1Nth.forEach(action-> {
System.out.println("Empl Details : "+ action);
});
}
}
package com.example.demo;
public class Employee {
private int empId;
private String empName;
private int empDepId;
private String status="active";
private int empSalary;
public Employee(int empId, String empName, int empDepId, String status, int empSalary) {
super();
this.empId = empId;
this.empName = empName;
this.empDepId = empDepId;
this.status = status;
this.empSalary = empSalary;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + empDepId;
result = prime * result + empId;
result = prime * result + ((empName == null) ? 0 : empName.hashCode());
result = prime * result + empSalary;
result = prime * result + ((status == null) ? 0 : status.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (empDepId != other.empDepId)
return false;
if (empId != other.empId)
return false;
if (empName == null) {
if (other.empName != null)
return false;
} else if (!empName.equals(other.empName))
return false;
if (empSalary != other.empSalary)
return false;
if (status == null) {
if (other.status != null)
return false;
} else if (!status.equals(other.status))
return false;
return true;
}
public int getEmpId() {
return empId;
}
public void setEmpId(int empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public int getEmpDepId() {
return empDepId;
}
public void setEmpDepId(int empDepId) {
this.empDepId = empDepId;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public int getEmpSalary() {
return empSalary;
}
public void setEmpSalary(int empSalary) {
this.empSalary = empSalary;
}
@Override
public String toString() {
return "Employee [empId=" + empId + ", empName=" + empName + ", empDepId=" + empDepId + ", status=" + status
+ ", empSalary=" + empSalary + "]";
}
}
Get Top 2 employees based on salary for each department
Comparator<Employee> bySalary =
Comparator.comparing(Employee::getSalary);
employeeList.stream().sorted(bySalary)
.collect(Collectors.groupingBy(e->e.getDepartment()))
.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey,
v->v.getValue().subList(0, 2),(a,b) -> a))
.forEach((k,v)->System.out.println("K "+k+" - V "+v));
This might be a simple solution comparing to others. We can use maxBy to get maximum salary for dept wise.
Map<String, Optional<Employee>> map = list.stream().collect(Collectors.groupingBy(Employee :: getDeptName,
Collectors.maxBy(Comparator.comparing(Employee :: getSalary))));
List<Employee> employeeList = new ArrayList<>();
employeeList.add(new Employee("Mayur", "IT", "100", 1000));
employeeList.add(new Employee("Raj", "IT", "101", 2000));
employeeList.add(new Employee("Anshul", "IT", "102", 3000));
employeeList.add(new Employee("Hari", "EC", "102", 3000));
employeeList.add(new Employee("Ram", "EC", "102", 3000));
Map<String, Optional<Employee>> map = employeeList.stream().collect(Collectors.groupingBy(Employee::getDepartment, Collectors.maxBy(Comparator.comparingInt(Employee::getSalary))));
map.entrySet().forEach(System.out::println);
Output :
IT=Optional[Employee{name='Anshul', department='IT', employeeID='102', salary=3000}]
EC=Optional[Employee{name='Hari', department='EC', employeeID='102', salary=30000}]
© 2022 - 2024 — McMap. All rights reserved.