Java > Java Collections Framework > Iterators and Streams > Collectors Utility
Grouping Students by Grade Level
This code snippet demonstrates how to use `Collectors.groupingBy()` to group a list of `Student` objects by their grade level. This is useful for generating reports, performing analysis, or organizing data based on a common attribute.
Code Example
This example defines a `Student` class with `name` and `gradeLevel` attributes. It then creates a list of `Student` objects. The `stream()` method creates a stream from the list. The `collect(Collectors.groupingBy(Student::getGradeLevel))` part groups the students based on their grade level. The `Student::getGradeLevel` is a method reference that extracts the grade level from each `Student` object, which is then used as the key for the resulting map. The values in the map are lists of students that belong to that grade level.
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
class Student {
private String name;
private int gradeLevel;
public Student(String name, int gradeLevel) {
this.name = name;
this.gradeLevel = gradeLevel;
}
public String getName() {
return name;
}
public int getGradeLevel() {
return gradeLevel;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", gradeLevel=" + gradeLevel +
'}';
}
}
public class CollectorsGroupingByExample {
public static void main(String[] args) {
List<Student> students = Arrays.asList(
new Student("Alice", 9),
new Student("Bob", 10),
new Student("Charlie", 9),
new Student("David", 10),
new Student("Eve", 11)
);
Map<Integer, List<Student>> studentsByGrade = students.stream()
.collect(Collectors.groupingBy(Student::getGradeLevel));
System.out.println(studentsByGrade);
// Output: {9=[Student{name='Alice', gradeLevel=9}, Student{name='Charlie', gradeLevel=9}], 10=[Student{name='Bob', gradeLevel=10}, Student{name='David', gradeLevel=10}], 11=[Student{name='Eve', gradeLevel=11}]}
}
}
Concepts Behind the Snippet
`Collectors.groupingBy()` is a versatile tool for partitioning stream elements into groups based on a classification function. It returns a `Map` where the keys are the results of the classification function, and the values are lists of elements that belong to each group. Method references provide a concise way to specify the classification function.
Real-Life Use Case
Consider an e-commerce application with a large catalog of products. You might use `Collectors.groupingBy()` to group products by category (e.g., "electronics", "clothing", "books"). This can be useful for generating category-specific reports, displaying category-based product listings, or performing category-level analysis.
Best Practices
When using `Collectors.groupingBy()`, consider the potential for a large number of groups. This could impact performance if the number of distinct keys is very high. Also, the default implementation uses a `HashMap`, which does not guarantee any specific order. If you need a specific order, you can use the overloaded version of `groupingBy()` that accepts a `Supplier` for the `Map` implementation (e.g., `TreeMap` for sorted keys).
When to use them
Use `Collectors.groupingBy()` when you need to categorize items in a stream based on a specific attribute or function. This is especially useful when generating reports, performing data analysis, or organizing data for display purposes.
Alternatives
Prior to Java 8, you would typically use a loop and a `Map` to manually group the elements. `Collectors.groupingBy()` provides a more declarative and often more efficient approach.
Pros
Concise and readable code, leverages streams for efficient grouping, allows for complex grouping logic using custom classification functions.
Cons
Potential performance impact with a very large number of groups, default implementation uses a `HashMap` (no guaranteed order).
FAQ
-
Can I specify a different `Map` implementation?
Yes, you can use the overloaded version of `groupingBy()` that accepts a `Supplier -
What if I want to perform additional aggregation within each group?
You can use the overloaded version of `groupingBy()` that accepts a downstream `Collector`. This allows you to perform additional operations on the elements within each group, such as calculating the average grade, or finding the highest-scoring student.