How to Use Collectors.groupingBy in Java: Simple Guide
In Java,
Collectors.groupingBy is used with streams to group elements of a collection by a classifier function, producing a Map where keys are the grouping criteria and values are lists of grouped items. It simplifies grouping tasks by combining with Stream.collect().Syntax
The basic syntax of Collectors.groupingBy is:
Collectors.groupingBy(classifier): Groups elements by the classifier function.classifier: A function that extracts the key to group by from each element.- Returns a
Map<K, List<T>>whereKis the key type andTis the element type.
You can also provide a downstream collector to customize the result, like counting or mapping.
java
Map<K, List<T>> groupedMap = collection.stream() .collect(Collectors.groupingBy(element -> element.getKey()));
Example
This example groups a list of strings by their first character using Collectors.groupingBy. It shows how to collect elements into a map where keys are the first letters and values are lists of strings starting with that letter.
java
import java.util.*; import java.util.stream.*; public class GroupingByExample { public static void main(String[] args) { List<String> words = Arrays.asList("apple", "banana", "apricot", "blueberry", "cherry"); Map<Character, List<String>> grouped = words.stream() .collect(Collectors.groupingBy(word -> word.charAt(0))); System.out.println(grouped); } }
Output
{a=[apple, apricot], b=[banana, blueberry], c=[cherry]}
Common Pitfalls
Common mistakes when using Collectors.groupingBy include:
- Using a classifier that returns
null, which causes aNullPointerException. - Expecting a sorted map but getting a regular
HashMapinstead. - Not specifying a downstream collector when you want aggregated results like counts.
To avoid these, ensure the classifier never returns null, use groupingBy(Function, Supplier, Collector) to specify map type, and use downstream collectors like Collectors.counting() when needed.
java
import java.util.*; import java.util.stream.*; public class GroupingByPitfall { public static void main(String[] args) { List<String> items = Arrays.asList("apple", null, "banana"); // This will throw NullPointerException because of null element // Map<Character, List<String>> result = items.stream() // .collect(Collectors.groupingBy(s -> s.charAt(0))); // Correct way: filter out nulls first Map<Character, List<String>> safeResult = items.stream() .filter(Objects::nonNull) .collect(Collectors.groupingBy(s -> s.charAt(0))); System.out.println(safeResult); } }
Output
{a=[apple], b=[banana]}
Quick Reference
| Usage | Description |
|---|---|
| Collectors.groupingBy(classifier) | Groups elements by classifier function into Map |
| Collectors.groupingBy(classifier, downstream) | Groups and applies downstream collector (e.g., counting, mapping) |
| Collectors.groupingBy(classifier, mapFactory, downstream) | Groups into a specific Map type with downstream collector |
| classifier function | Function to extract key for grouping from each element |
| downstream collector | Collector to apply to grouped elements (optional) |
Key Takeaways
Use Collectors.groupingBy with a classifier function to group stream elements into a Map.
Always ensure the classifier function does not return null to avoid exceptions.
Use downstream collectors like counting() to aggregate grouped data beyond lists.
Specify map type if you need a sorted or specific Map implementation.
Filter out null elements before grouping to prevent runtime errors.