In SQL, the GROUP BY statement returns the set of records having the same value in particular criteria. For example, you have a table that contains student information, each student coming from a different country. Use the GROUP BY statement according to national criteria, you can know the number of students from some countries. Similarly, from version 8, Java also supports us by the group by function. In this tutorial, I will show you how to group by using Stream and Collectors in Java.
For example, I have a list of students with the following information:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
package com.huongdanjava.javaexample; public class Student { private String name; private String country; public Student(String name, String country) { this.name = name; this.country = country; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((country == null) ? 0 : country.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Student other = (Student) obj; if (country == null) { if (other.country != null) return false; } else if (!country.equals(other.country)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", country='" + country + '\'' + '}'; } } |
1 2 3 4 5 |
List<Student> names = Arrays.asList( new Student("Khanh", "VN"), new Student("Peter", "US"), new Student("Thanh", "VN"), new Student("Khanh", "VN")); |
Now, I need to group the above student list by country and count the number of students in each country.
To do this, we will use the collect() method in the Stream object with the groupingBy() static method in the Java Collectors object.
For example, if we need a group of students by country, we would like to code as follows:
1 2 |
Map<String, List<Student>> result = names.stream() .collect(Collectors.groupingBy(Student::getCountry)); |
Result:
In the code above, the parameter of the groupingBy() method is the same as the criteria in the SQL. If you want to group by student name then you can replace Student::getCountry with Student::getName.
As you can see, by default after the group is finished, any element that has the same criteria falls into a List object, we can change this by passing another parameter to the groupingBy() method of the Collectors object. For example, now that I want the elements with the same criteria to be in a Set object, I would like to code as follows:
1 2 |
Map<String, Set<Student>> result = names.stream() .collect(Collectors.groupingBy(Student::getCountry, Collectors.toSet())); |
Result:
Also, if after grouping, you want to count the number of students in each country, then use the groupingBy method as follows:
1 2 |
Map<String, Long> result = names.stream() .collect(Collectors.groupingBy(Student::getCountry, Collectors.counting())); |
Here, I used another method of the Collectors object called counting() to count the number of students in each country that I wanted.
Result: