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-
-
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
- 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>.
- 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
You may also like-
No comments:
Post a Comment