Java 8 lambda for selecting top salary employee for each department
Asked Answered
T

11

8
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.

Tetreault answered 16/3, 2016 at 16:3 Comment(0)
G
17

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.

Giraud answered 16/3, 2016 at 16:12 Comment(0)
W
7

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.

Wheelchair answered 16/3, 2016 at 16:24 Comment(0)
H
3

/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);
Hypochromia answered 20/6, 2019 at 18:36 Comment(0)
S
1

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.

Scenery answered 9/5, 2019 at 16:26 Comment(0)
L
0

Map<String, Optional> result = li.stream().collect(Collectors.groupingBy(Emp::getDept, Collectors.reducing(BinaryOperator.maxBy(Comparator.comparing(Emp::getSalary))) ));

Lithesome answered 10/11, 2021 at 19:13 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Nerveless
C
0

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)
               )
               );
Chickadee answered 26/5, 2022 at 10:59 Comment(0)
R
0
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));
Roselinerosella answered 17/10, 2022 at 7:16 Comment(0)
C
0
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 + "]";
    }
    
    
    
}
Cutright answered 6/2, 2023 at 16:25 Comment(0)
M
0
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));
Michi answered 12/4, 2023 at 14:13 Comment(0)
R
0

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))));
Rockies answered 3/2 at 1:53 Comment(0)
B
-1
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}]
Beau answered 3/6, 2022 at 10:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.