Collectors in Java 8 – With Examples:

Collectors is a class which has been introduced in Java 8 and most commonly used as last step of Stream operations.

Implementations of Collector that implement various useful reduction operations, such as accumulating elements into collections, summarizing elements according to various criteria, etc.

There are various methods in Collectors, In this article let us see methods of collectors with examples.

  • Collectors.groupingBy
  • Collectors.mapping
  • Collectors.filtering
  • Collectors.partitioningBy
  • Collectors.counting
  • Collectors.summingInt

Let us see all these methods with examples with various scenario’s.

Collectors.groupingBy:

  • It is used to group based on a property and returns the result in Map.

Let us create an employee class for the example,

package model;

public class Employee{

    private int id;
    private String name;
    private String department;
    private int salary;


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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDepartment() {
        return department;
    }

    public void setDepartment(String department) {
        this.department = department;
    }

    public int getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", department='" + department + '\'' +
                ", salary=" + salary +
                '}';
    }
}

Employee.java

Collectors.groupingBy: GroupingBy Employee Department:

public class CollectorsGroupBy {

    public static void main(String args[]) {

        List<Employee> employeeList =
                Arrays.asList(new Employee(5, "Harry", "System Admin", 50000),
                new Employee(1, "Melanie", "Front Desk", 10000),
                new Employee(2, "Hikari", "Executive", 5000),
                new Employee(3, "Eel", "Executive", 5000),
                new Employee(4, "Alphabite", "Executive", 5000),
                new Employee(6, "Messy", "Front Desk", 10000));

        //Grouping by employees department
        Map<String, List<Employee>> groupByDepartment =
                employeeList.stream().collect(Collectors.groupingBy(Employee::getDepartment));

        System.out.println("Group by Department");
        groupByDepartment.forEach((k, v) -> {
            System.out.println("Key is: " +k);
            System.out.println("Value: "+v);
        });
    }
}

GroupingBy Department

Output:

Group by Department
Key is: Executive
Value: [Employee{id=2, name=’Hikari’, department=’Executive’, salary=5000}, Employee{id=3, name=’Eel’, department=’Executive’, salary=5000}, Employee{id=4, name=’Alphabite’, department=’Executive’, salary=5000}]
Key is: Front Desk
Value: [Employee{id=1, name=’Melanie’, department=’Front Desk’, salary=10000}, Employee{id=6, name=’Messy’, department=’Front Desk’, salary=10000}]
Key is: System Admin
Value: [Employee{id=5, name=’Harry’, department=’System Admin’, salary=50000}]

Collectors.groupingBy: Sort by Employee name and Group by Department:

public class CollectorsGroupBy {

    public static void main(String args[]) {

        List<Employee> employeeList =
                Arrays.asList(new Employee(5, "Harry", "System Admin", 50000),
                new Employee(1, "Melanie", "Front Desk", 10000),
                new Employee(2, "Hikari", "Executive", 5000),
                new Employee(3, "Eel", "Executive", 5000),
                new Employee(4, "Alphabite", "Executive", 5000),
                new Employee(6, "Messy", "Front Desk", 10000));


        Map<String, List<Employee>> sortAndGroupBy = employeeList.stream().sorted(Comparator.comparing(Employee::getName)).collect(Collectors.groupingBy(Employee::getDepartment));

        System.out.println("Sort by name and group by Department");
        sortAndGroupBy.forEach((k, v) -> {
            System.out.println("Key is: " +k);
            System.out.println("Value: "+v);
        });
    }
}

Sorting by name and grouping by department

Output:

Sort by name and group by Department
Key is: Front Desk
Value: [Employee{id=1, name=’Melanie’, department=’Front Desk’, salary=10000}, Employee{id=6, name=’Messy’, department=’Front Desk’, salary=10000}]
Key is: System Admin
Value: [Employee{id=5, name=’Harry’, department=’System Admin’, salary=50000}]
Key is: Executive
Value: [Employee{id=4, name=’Alphabite’, department=’Executive’, salary=5000}, Employee{id=3, name=’Eel’, department=’Executive’, salary=5000}, Employee{id=2, name=’Hikari’, department=’Executive’, salary=5000}]

We have grouped the employees by department and each department has employee’s name in sorted order.

Collectors.groupingBy: Multiple groupingBy:

public class CollectorsGroupBy {

    public static void main(String args[]) {

        List<Employee> employeeList =
                Arrays.asList(new Employee(5, "Harry", "System Admin", 50000),
                        new Employee(1, "Melanie", "Front Desk", 10000),
                        new Employee(2, "Hikari", "Executive", 5000),
                        new Employee(3, "Eel", "Executive", 5000),
                        new Employee(4, "Alphabite", "Executive", 5000),
                        new Employee(6, "Messy", "Front Desk", 10000));

        Map<String, Map<Integer, List<Employee>>> empData = employeeList.stream().collect(Collectors.groupingBy(Employee::getDepartment, Collectors.groupingBy(Employee::getId)));

        System.out.println("Multiple groupingBy - department and id");
        empData.forEach((k, v) -> {
            System.out.println("Key: " + k);
            v.entrySet().forEach(s -> {
                System.out.println("sub-Key is: " + s.getKey());
                System.out.println("sub-Value is: " + s.getValue());
            });
        });
    }
}

Multiple GroupingBy – Department and Id

Output:

Multiple groupingBy – department and id
Key: Executive
sub-Key is: 2
sub-Value is: [Employee{id=2, name=’Hikari’, department=’Executive’, salary=5000}]
sub-Key is: 3
sub-Value is: [Employee{id=3, name=’Eel’, department=’Executive’, salary=5000}]
sub-Key is: 4
sub-Value is: [Employee{id=4, name=’Alphabite’, department=’Executive’, salary=5000}]
Key: Front Desk
sub-Key is: 1
sub-Value is: [Employee{id=1, name=’Melanie’, department=’Front Desk’, salary=10000}]
sub-Key is: 6
sub-Value is: [Employee{id=6, name=’Messy’, department=’Front Desk’, salary=10000}]
Key: System Admin
sub-Key is: 5
sub-Value is: [Employee{id=5, name=’Harry’, department=’System Admin’, salary=50000}]

From the output, first grouping is done based on department and second grouping is done based on ID.

Sorting based on Multiple Fields using Stream and Grouping:

public class CollectorsGroupBy {

    public static void main(String args[]) {

        List<Employee> employeeList =
                Arrays.asList(new Employee(5, "Harry", "System Admin", 50000),
                        new Employee(1, "Melanie", "Front Desk", 10000),
                        new Employee(2, "Hikari", "Executive", 5000),
                        new Employee(3, "Eel", "Executive", 5000),
                        new Employee(4, "Alphabite", "Executive", 5000),
                        new Employee(6, "Messy", "Front Desk", 10000));

        Map<String, List<Employee>> multisortAndGrouping = employeeList.stream().sorted(Comparator.comparing(Employee::getName).thenComparing(Employee::getId)).collect(Collectors.groupingBy(Employee::getDepartment));
        System.out.println("Multiple sorting - Name and Id - and grouping");
        multisortAndGrouping.forEach((k, v) -> {
            System.out.println("Key is: " + k);
            System.out.println("Value: " + v);
        });
    }
}

Multiple Fields sorting using Streams

Output:

Multiple sorting – Name and Id – and grouping
Key is: Front Desk
Value: [Employee{id=1, name=’Melanie’, department=’Front Desk’, salary=10000}, Employee{id=6, name=’Messy’, department=’Front Desk’, salary=10000}]
Key is: System Admin
Value: [Employee{id=5, name=’Harry’, department=’System Admin’, salary=50000}]
Key is: Executive
Value: [Employee{id=4, name=’Alphabite’, department=’Executive’, salary=5000}, Employee{id=3, name=’Eel’, department=’Executive’, salary=5000}, Employee{id=2, name=’Hikari’, department=’Executive’, salary=5000}]

Collectors.counting:

public class CollectorsGroupBy {

    public static void main(String args[]) {

        List<Employee> employeeList =
                Arrays.asList(new Employee(5, "Harry", "System Admin", 50000),
                        new Employee(1, "Melanie", "Front Desk", 10000),
                        new Employee(2, "Hikari", "Executive", 5000),
                        new Employee(3, "Eel", "Executive", 5000),
                        new Employee(4, "Alphabite", "Executive", 5000),
                        new Employee(6, "Messy", "Front Desk", 10000));

        Map<String, Long> counting = employeeList.stream().collect(Collectors.groupingBy(Employee::getDepartment, Collectors.counting()));
        System.out.println("Counting the collectors");
        counting.forEach((k, v) -> {
            System.out.println("Key is: " + k);
            System.out.println("Value: " + v);
        });
    }
}

Collectors.counting

Collectors.counting helps us with count, number of elements in the group.

Output:

Counting the collectors
Key is: Executive
Value: 3
Key is: Front Desk
Value: 2
Key is: System Admin
Value: 1

Collectors.summingInt:

Collectors.summingInt helps us to sum the total value.

public class CollectorsGroupBy {

    public static void main(String args[]) {

        List<Employee> employeeList =
                Arrays.asList(new Employee(5, "Harry", "System Admin", 50000),
                        new Employee(1, "Melanie", "Front Desk", 10000),
                        new Employee(2, "Hikari", "Executive", 5000),
                        new Employee(3, "Eel", "Executive", 5000),
                        new Employee(4, "Alphabite", "Executive", 5000),
                        new Employee(6, "Messy", "Front Desk", 10000));

        Map<String, Integer> summingSalary = employeeList.stream().collect(Collectors.groupingBy(Employee::getDepartment, Collectors.summingInt(Employee::getSalary)));
        System.out.println("Summing the salary");
        summingSalary.forEach((k, v) -> {
            System.out.println("Key is: " + k);
            System.out.println("Value: " + v);
        });
    }
}

Collectors.summingInt

Here we are summing all the salaries of the employee based on each department.

Output:

Summing the salary
Key is
: Executive
Value: 15000
Key is: Front Desk
Value: 20000
Key is: System Admin
Value: 50000

Collectors.partitioningBy:

Collectors.paritioningBy returns boolean as a key, where when condition met the key is true and when condition not met the key is false.

public class CollectorsGroupBy {

    public static void main(String args[]) {

        List<Employee> employeeList =
                Arrays.asList(new Employee(5, "Harry", "System Admin", 50000),
                        new Employee(1, "Melanie", "Front Desk", 10000),
                        new Employee(2, "Hikari", "Executive", 5000),
                        new Employee(3, "Eel", "Executive", 5000),
                        new Employee(4, "Alphabite", "Executive", 5000),
                        new Employee(6, "Messy", "Front Desk", 10000));

        Map<Boolean, List<Employee>> partitioningBy = employeeList.stream().collect(Collectors.partitioningBy(s -> s.getSalary() > 5000));
        System.out.println("PartitioningBy");
        partitioningBy.forEach((k, v) -> {
            System.out.println("Key is: " + k);
            System.out.println("Value: " + v);
        });
    }
}

Collectors.paritioningBy

We have set a condition where salary is greater than 5000. If the condition is met those records will have the key as true, and other records will have key as false.

Output:

PartitioningBy
Key is: false
Value: [Employee{id=2, name=’Hikari’, department=’Executive’, salary=5000}, Employee{id=3, name=’Eel’, department=’Executive’, salary=5000}, Employee{id=4, name=’Alphabite’, department=’Executive’, salary=5000}]
Key is: true
Value: [Employee{id=5, name=’Harry’, department=’System Admin’, salary=50000}, Employee{id=1, name=’Melanie’, department=’Front Desk’, salary=10000}, Employee{id=6, name=’Messy’, department=’Front Desk’, salary=10000}]

Collectors.mapping:

It helps to map a specific property to the groupingBy property.

public class CollectorsGroupBy {

    public static void main(String args[]) {

        List<Employee> employeeList =
                Arrays.asList(new Employee(5, "Harry", "System Admin", 50000),
                        new Employee(1, "Melanie", "Front Desk", 10000),
                        new Employee(2, "Hikari", "Executive", 5000),
                        new Employee(3, "Eel", "Executive", 5000),
                        new Employee(4, "Alphabite", "Executive", 5000),
                        new Employee(6, "Messy", "Front Desk", 10000));



        Map<String, List<String>> mapping = employeeList.stream().collect(Collectors.groupingBy(Employee::getDepartment, Collectors.mapping(Employee::getName, Collectors.toList())));
        System.out.println("Mapping by");
        mapping.forEach((k, v) -> {
            System.out.println("Key is: " + k);
            System.out.println("Value: " + v);
        });
    }
}

Collectors.mapping

Here we are groupingBy departing and mapping only the employee names.

Output:

Mapping by
Key is: Executive
Value: [Hikari, Eel, Alphabite]
Key is: Front Desk
Value: [Melanie, Messy]
Key is: System Admin
Value: [Harry]

Collectors.filtering:

Collectors.filtering helps us to filter out the records based on the groupingBy property.

public class CollectorsGroupBy {

    public static void main(String args[]) {

        List<Employee> employeeList =
                Arrays.asList(new Employee(5, "Harry", "System Admin", 50000),
                        new Employee(1, "Melanie", "Front Desk", 10000),
                        new Employee(2, "Hikari", "Executive", 5000),
                        new Employee(3, "Eel", "Executive", 5000),
                        new Employee(4, "Alphabite", "Executive", 5000),
                        new Employee(6, "Messy", "Front Desk", 10000));
        Map<String, List<Employee>> filter = employeeList.stream().collect(Collectors.groupingBy(Employee::getDepartment, Collectors.filtering(s -> s.getSalary() > 10000, Collectors.toList())));
        System.out.println("Filtering by");
        filter.forEach((k, v) -> {
            System.out.println("Key is: " + k);
            System.out.println("Value: " + v);
        });

    }
}

Collectors.filtering

Here we are filtering the employees who have salary greater than 10000 in each department.

Output:

Filtering by
Key is: Executive
Value: []
Key is: Front Desk
Value: []
Key is: System Admin
Value: [Employee{id=5, name=’Harry’, department=’System Admin’, salary=50000}]

Please find the complete code,

import model.Employee;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class CollectorsGroupBy {

    public static void main(String args[]) {

        List<Employee> employeeList =
                Arrays.asList(new Employee(5, "Harry", "System Admin", 50000),
                        new Employee(1, "Melanie", "Front Desk", 10000),
                        new Employee(2, "Hikari", "Executive", 5000),
                        new Employee(3, "Eel", "Executive", 5000),
                        new Employee(4, "Alphabite", "Executive", 5000),
                        new Employee(6, "Messy", "Front Desk", 10000));

        //Grouping by employees department
        Map<String, List<Employee>> groupByDepartment =
                employeeList.stream().collect(Collectors.groupingBy(Employee::getDepartment));

        System.out.println("Group by Department");
        groupByDepartment.forEach((k, v) -> {
            System.out.println("Key is: " + k);
            System.out.println("Value: " + v);
        });


        Map<String, List<Employee>> sortAndGroupBy = employeeList.stream().sorted(Comparator.comparing(Employee::getName)).collect(Collectors.groupingBy(Employee::getDepartment));

        System.out.println("Sort by name and group by Department");
        sortAndGroupBy.forEach((k, v) -> {
            System.out.println("Key is: " + k);
            System.out.println("Value: " + v);
        });

        Map<String, Map<Integer, List<Employee>>> empData = employeeList.stream().collect(Collectors.groupingBy(Employee::getDepartment, Collectors.groupingBy(Employee::getId)));

        System.out.println("Multiple groupingBy - department and id");
        empData.forEach((k, v) -> {
            System.out.println("Key: " + k);
            v.entrySet().forEach(s -> {
                System.out.println("sub-Key is: " + s.getKey());
                System.out.println("sub-Value is: " + s.getValue());
            });
        });

        Map<String, List<Employee>> multisortAndGrouping = employeeList.stream().sorted(Comparator.comparing(Employee::getName).thenComparing(Employee::getId)).collect(Collectors.groupingBy(Employee::getDepartment));
        System.out.println("Multiple sorting - Name and Id - and grouping");
        multisortAndGrouping.forEach((k, v) -> {
            System.out.println("Key is: " + k);
            System.out.println("Value: " + v);
        });

        Map<String, Long> counting = employeeList.stream().collect(Collectors.groupingBy(Employee::getDepartment, Collectors.counting()));
        System.out.println("Counting the collectors");
        counting.forEach((k, v) -> {
            System.out.println("Key is: " + k);
            System.out.println("Value: " + v);
        });

        Map<String, Integer> summingSalary = employeeList.stream().collect(Collectors.groupingBy(Employee::getDepartment, Collectors.summingInt(Employee::getSalary)));
        System.out.println("Summing the salary");
        summingSalary.forEach((k, v) -> {
            System.out.println("Key is: " + k);
            System.out.println("Value: " + v);
        });

        Map<Boolean, List<Employee>> partitioningBy = employeeList.stream().collect(Collectors.partitioningBy(s -> s.getSalary() > 5000));
        System.out.println("PartitioningBy");
        partitioningBy.forEach((k, v) -> {
            System.out.println("Key is: " + k);
            System.out.println("Value: " + v);
        });

        Map<String, List<String>> mapping = employeeList.stream().collect(Collectors.groupingBy(Employee::getDepartment, Collectors.mapping(Employee::getName, Collectors.toList())));
        System.out.println("Mapping by");
        mapping.forEach((k, v) -> {
            System.out.println("Key is: " + k);
            System.out.println("Value: " + v);
        });

        Map<String, List<Employee>> filter = employeeList.stream().collect(Collectors.groupingBy(Employee::getDepartment, Collectors.filtering(s -> s.getSalary() > 10000, Collectors.toList())));
        System.out.println("Filtering by");
        filter.forEach((k, v) -> {
            System.out.println("Key is: " + k);
            System.out.println("Value: " + v);
        });

    }
}

Please do post your queries in comments!

By Sri

Leave a Reply

Your email address will not be published. Required fields are marked *