Search code examples
javajava-8java-stream

Java 8 Streams API grouping by two fields and return updated Collection


I have java custom class i.e Employee having below fields,

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

public Employee(String name, String dept, Integer age, Double salary) {
    this.name = name;
    this.dept = dept;
    this.salary = salary;
    this.age = age;
}
//getter and setters

My list object has below data,

List<Employee> list = Arrays.asList(
            new Employee("mahesh", "IT", 25, 1000.00), 
            new Employee("rajesh", "IT", 30, 1200.00), 
            new Employee("Saket", "IT", 30, 1000.00), 
            new Employee("Samuel", "IT", 30, 1150.00), 
            new Employee("Anil", "Eng", 29, 2000.00),
            new Employee("Sachin", "Eng", 29, 2000.00));

I have to iterate this list and updated list should return first, third, fifth and sixth records. group the records using department and salary and if the grouping count greater than 1 those records should return. In the above example, second and fourth it's occured one time as grouping so those records should skip.

So final List should contain these records,

 List<Employee> list = Arrays.asList(
            new Employee("mahesh", "IT", 25, 1000.00), 
            new Employee("Saket", "IT", 30, 1000.00), 
            new Employee("Anil", "Eng", 29, 2000.00),
            new Employee("Sachin", "Eng", 29, 2000.00));

Need to group based on two fields i.e department and salary and the stream api should return updated list.


Solution

  • If you are interested in elements that are not unique when grouped by a combination of department and salary, you can perform a grouping and filter based on the count. This would further need flat mapping the elements back for the data structure desired in the output:

        List<Employee> employees = list.stream()
                .collect(Collectors.groupingBy(employee -> employee.dept + employee.salary))
                .entrySet()
                .stream()
                .filter(e -> e.getValue().size() > 1)
                .flatMap(e -> e.getValue().stream())
                .collect(Collectors.toList());
    

    Note: This relies on the uniqueness of the key created with the combination of department and salary represented as of type String.