Wednesday, December 1, 2021

Java Stream - Collectors.groupingBy() With Examples

If you want to group the elements of the stream as per some classification then you can use the Collectors.groupingBy() method which is a static method in the Collectors class with in the Java Stream API.

Syntax of Collectors.groupingBy() method

There are three overloaded groupingBy() methods-

  1. Collector<T,?,Map<K,List<T>>> groupingBy(Function<? super T,? extends K> classifier)- This method groups elements according to the passed classification function which is an implementation of Function functional interface and returns the results in a Map.

    The collector produces a Map<K, List<T>> whose keys are the values resulting from applying the classification function to the input elements and corresponding values for each groups are stored in Lists

  2. Collector<T,?,Map<K,D>> groupingBy(Function<? super T,? extends K> classifier, Collector<? super T,A,D> downstream)- This method groups elements according to the passed classification function and then performs a reduction operation on the values associated with a given key using the specified downstream Collector passed as second argument. The resulting collector produces a Map<K, D>.
  3. Collector<T,?,M> groupingBy(Function<? super T,? extends K> classifier, Supplier<M> mapFactory, Collector<? super T,A,D> downstream)- This method groups elements according to the passed classification function and then performs a reduction operation on the values associated with a given key using the specified downstream Collector (third argument). The Map produced by the Collector is created with the supplied factory function (second argument).

Collectors.groupingBy() Java examples

For the examples we’ll use the objects of Employee class-

public class Employee {
  private String empId;
  private int age;
  private String name;
  private char gender;
  private int salary;
  Employee(String empId, int age, String name, char gender, int salary){
    this.empId = empId;
    this.age = age;
    this.name = name;
    this.gender = gender;
    this.salary = salary;
  }
  public String getEmpId() {
    return empId;
  }

  public int getAge() {
    return age;
  }

  public String getName() {
    return name;
  }

  public char getGender() {
    return gender;
  }

  public int getSalary() {
    return salary;
  }
  @Override
  public String toString() {
    return "Emp Id: " +  getEmpId() + " Name: " + getName() + " Age: " + getAge();
  }
}

1. If you want to group the employees by gender so that you get a Map having two keys “M” and “F” and two lists associated with these keys having the segregated employees.

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

public class GroupingByDemo {

  public static void main(String[] args) {
    List<Employee> empList = Arrays.asList(new Employee("E001", 40, "Ram", 'M', 5000), 
                new Employee("E002", 35, "Shelly", 'F', 7000), 
                new Employee("E003", 40, "Remington", 'M', 5000), 
                new Employee("E004", 37, "Bianca", 'F', 11000),
                new Employee("E005", 35, "Dominic", 'M', 7000), 
        new Employee("E006", 28, "Amanda", 'F', 14000));
    Map<Character, List<Employee>> empMap = empList.stream().collect(Collectors.groupingBy(Employee :: getGender));
    // Displaying groups by iterating Map
    empMap.entrySet().forEach(es -> {System.out.println("Gender- " + es.getKey());
        System.out.println("---Employees List---");
        es.getValue().forEach(e->System.out.println(e));});
  }
}

Output

Gender- F
---Employees List---
Emp Id: E002 Name: Shelly Age: 35
Emp Id: E004 Name: Bianca Age: 37
Emp Id: E006 Name: Amanda Age: 28
Gender- M
---Employees List---
Emp Id: E001 Name: Ram Age: 40
Emp Id: E003 Name: Remington Age: 40
Emp Id: E005 Name: Dominic Age: 35

2. After grouping the employees by gender if you want to collect the name of the employees in a Set then that collector can be passed as a second argument to the groupingBy() method.

public class GroupingByDemo {

  public static void main(String[] args) {
    List<Employee> empList = Arrays.asList(new Employee("E001", 40, "Ram", 'M', 5000), 
                new Employee("E002", 35, "Shelly", 'F', 7000), 
                new Employee("E003", 40, "Remington", 'M', 5000), 
                new Employee("E004", 37, "Bianca", 'F', 11000),
                new Employee("E005", 35, "Dominic", 'M', 7000), 
        new Employee("E006", 28, "Amanda", 'F', 14000));
    Map<Character, Set<String>> empNames = empList.stream()
                            .collect(Collectors.groupingBy(Employee::getGender,
                                Collectors.mapping(Employee::getName, Collectors.toSet())));
    // Displaying groups by iterating Map
    empNames.entrySet().forEach(es -> {System.out.println("Gender- " + es.getKey());
        System.out.println("---Employees List---");
        es.getValue().forEach(e->System.out.println(e));});
  }
}

Output

Gender- F
---Employees List---
Shelly
Bianca
Amanda
Gender- M
---Employees List---
Dominic
Remington
Ram

3. If you want the Max salary in each group then you can pass Collectors.maxBy as a second argument.

public class GroupingByDemo {

  public static void main(String[] args) {
    List<Employee> empList = Arrays.asList(new Employee("E001", 40, "Ram", 'M', 5000), 
                new Employee("E002", 35, "Shelly", 'F', 7000), 
                new Employee("E003", 40, "Remington", 'M', 5000), 
                new Employee("E004", 37, "Bianca", 'F', 11000),
                new Employee("E005", 35, "Dominic", 'M', 7000), 
        new Employee("E006", 28, "Amanda", 'F', 14000));
    Map<Character, Optional<Employee>> empNames = empList.stream()
                            .collect(Collectors.groupingBy(Employee::getGender,
                                Collectors.maxBy(Comparator.comparingInt(Employee::getSalary))));
    // Displaying groups by iterating Map
    empNames.entrySet().forEach(es -> {System.out.println("Gender- " + es.getKey());
        System.out.println(" Employee Name- " + es.getValue().get().getName() +  
              " Salary- " + es.getValue().get().getSalary());});
  }
}

Output

Gender- F
 Employee Name- Amanda Salary- 14000
Gender- M
 Employee Name- Dominic Salary- 7000

4. If you want to group the employees by age and also want to ensure that keys (age) are in sorted order then you can collect the results in a TreeMap so that keys are in sorted order. In that scenario Collectors.groupingBy() method with three arguments can be used.

public class GroupingByDemo {

  public static void main(String[] args) {
    List<Employee> empList = Arrays.asList(new Employee("E001", 40, "Ram", 'M', 5000), 
                new Employee("E002", 35, "Shelly", 'F', 7000), 
                new Employee("E003", 40, "Remington", 'M', 5000), 
                new Employee("E004", 37, "Bianca", 'F', 11000),
                new Employee("E005", 35, "Dominic", 'M', 7000), 
        new Employee("E006", 28, "Amanda", 'F', 14000));
    Map<Integer, Set<String>> empNames = empList.stream()
                            .collect(Collectors.groupingBy(e -> e.getAge(), TreeMap::new,
                                Collectors.mapping(Employee::getName, Collectors.toSet())));
    // Displaying groups by iterating Map
    empNames.entrySet().forEach(es -> {System.out.println("Age- " + es.getKey());
      System.out.println("---Employees---");
      es.getValue().forEach(name -> System.out.println(name));
    });
  }
}

Output

Age- 28
---Employees---
Amanda
Age- 35
---Employees---
Shelly
Dominic
Age- 37
---Employees---
Bianca
Age- 40
---Employees---
Remington
Ram

That's all for this topic Java Stream - Collectors.groupingBy() With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Java Stream - filter() With Examples
  2. Java Stream - skip() With Examples
  3. Java Stream - findFirst() With Examples
  4. Java Stream - sorted() With Examples
  5. Java Stream API Interview Questions And Answers

You may also like-

  1. Volatile Keyword in Java With Examples
  2. Garbage Collection in Java
  3. Transient Keyword in Java With Examples
  4. Java Application With User Input in Docker Container
  5. instanceof Operator in Java With Examples
  6. How to Display Time in AM-PM Format in Java
  7. Spring depends-on Attribute
  8. Spring Asynchronous Method Execution Support Using @Async Annotation

No comments:

Post a Comment