Java 8 lambda for selecting top salary employee for each department

Viewed 29975
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.

7 Answers

/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)
               )
               );
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}]
Related