How to apply Filtering on groupBy in java streams

Niraj Sonawane picture Niraj Sonawane · Jan 16, 2018 · Viewed 14.2k times · Source

How do you group first and then apply filtering using Java streams?

Example: Consider this Employee class: I want to group by Department with a list of an employee having a salary greater than 2000.

public class Employee {
    private String department;
    private Integer salary;
    private String name;

    //getter and setter

    public Employee(String department, Integer salary, String name) {
        this.department = department;
        this.salary = salary;
        this.name = name;
    }
}   

This is how I can do this

List<Employee> list   = new ArrayList<>();
list.add(new Employee("A", 5000, "A1"));
list.add(new Employee("B", 1000, "B1"));
list.add(new Employee("C", 6000, "C1"));
list.add(new Employee("C", 7000, "C2"));

Map<String, List<Employee>> collect = list.stream()
    .filter(e -> e.getSalary() > 2000)
    .collect(Collectors.groupingBy(Employee::getDepartment));  

Output

{A=[Employee [department=A, salary=5000, name=A1]],
 C=[Employee [department=C, salary=6000, name=C1], Employee [department=C, salary=7000, name=C2]]}

As there are no employees in Department B with a salary greater than 2000. So there is no key for Department B: But actually, I want to have that key with empty list –

Expected output

{A=[Employee [department=A, salary=5000, name=A1]],
 B=[],
 C=[Employee [department=C, salary=6000, name=C1], Employee [department=C, salary=7000, name=C2]]}

How can we do this?

Answer

Naman picture Naman · Jan 16, 2018

You can make use of the Collectors.filtering API introduced since Java-9 for this:

Map<String, List<Employee>> output = list.stream()
            .collect(Collectors.groupingBy(Employee::getDepartment,
                    Collectors.filtering(e -> e.getSalary() > 2000, Collectors.toList())));

Important from the API note :

  • The filtering() collectors are most useful when used in a multi-level reduction, such as downstream of a groupingBy or partitioningBy.

  • A filtering collector differs from a stream's filter() operation.