Published 29 Oct, 2022

Java - Java stream groupingBy key as max salary employee and value as all employee of department

Category Java
Modified : Nov 28, 2022
102

I have a list of Employee

public class Employee {
  private String name;
  private Integer age;
  private Double salary;
  private Department department;
}

List<Employee> employeeList = Arrays.asList(
      new Employee("Tom Jones", 45, 12000.00,Department.MARKETING),
      new Employee("Harry Major", 26, 20000.00, Department.LEGAL),
      new Employee("Ethan Hardy", 65, 30000.00, Department.LEGAL),
      new Employee("Nancy Smith", 22, 15000.00, Department.MARKETING),
      new Employee("Catherine Jones", 21, 18000.00, Department.HR),
      new Employee("James Elliot", 58, 24000.00, Department.OPERATIONS),
      new Employee("Frank Anthony", 55, 32000.00, Department.MARKETING),
      new Employee("Michael Reeves", 40, 45000.00, Department.OPERATIONS));

I want to get Map<Employee, List<Employee>> where map key is for each Department's max salary employee and value is all employee of that department. I am trying to groupingBy but it gives all employee with Department map. How to get all max salary employee as map key ?

Map<Department,List<Employee>> employeeMap
        = employeeList.stream().collect(Collectors.groupingBy(Employee::getDepartment));

Answers

There are 3 suggested solutions here and each one has been listed below with a detailed description. The following topics have been covered briefly such as Java, Java Stream. These have been categorized in sections for a clear and precise explanation.

4

You can get the required result as follows:

Map<Employee, List<Employee>> result = employees.stream()
         .sorted(Comparator.comparingDouble(Employee::getSalary).reversed())
         .collect(groupingBy(Employee::getDepartment, LinkedHashMap::new, toList())).values().stream()
         .collect(toMap(l -> l.get(0), Function.identity()));

There's probably better and more efficient solutions out there and I would have exhausted those ideas had i not been on my phone.


44

This seems to work.

  • It first determines the employees by department then
  • Then it groups them based on the largest salary of the departments employee
Map<Employee, List<Employee>> map = employeeList.stream()
        .collect(Collectors.groupingBy(Employee::getDepartment))
        .entrySet().stream()
        .collect(Collectors.toMap(
                e->e.getValue().stream()
                        .max(Comparator.comparing(
                                Employee::getSalary))
                        .get(),
                Entry::getValue));

Overriding toString in Employee class to return name, salary, and department, here is the output.

map.forEach((k,v)->
    System.out.println();
});

Prints

Frank Anthony, 32000.0, MARKETING}
    
    
    


    
    


    


    
    


20

You can do this:

Map<Employee, List<Employee>> employeeMap = employeeList.stream()
      .collect(groupingBy(Employee::getDepartment))
      .values().stream()
      .collect(
        groupingBy(
            (es) -> es.stream()
              .max(Comparator.comparing(e -> e.getSalary())).get()
        )
      ).entrySet().stream()
      .collect(toMap(
        Map.Entry::getKey,
        e -> e.getValue().iterator().next()
      ));

Output:

{(Michael Reeves, 40, 45000.0, OPERATIONS)=[(James Elliot, 58, 24000.0, OPERATIONS), (Michael Reeves, 40, 45000.0, OPERATIONS)], 
(Catherine Jones, 21, 18000.0, HR)=[(Catherine Jones, 21, 18000.0, HR)], 
(Ethan Hardy, 65, 30000.0, LEGAL)=[(Harry Major, 26, 20000.0, LEGAL), (Ethan Hardy, 65, 30000.0, LEGAL)], 
(Frank Anthony, 55, 32000.0, MARKETING)=[(Tom Jones, 45, 12000.0, MARKETING), (Nancy Smith, 22, 15000.0, MARKETING), (Frank Anthony, 55, 32000.0, MARKETING)]}

Link to repl.it: https://repl.it/repls/CluelessAwesomeLevel#Main.java