0
0
JavaHow-ToBeginner · 3 min read

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>> where K is the key type and T is 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 a NullPointerException.
  • Expecting a sorted map but getting a regular HashMap instead.
  • 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

UsageDescription
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 functionFunction to extract key for grouping from each element
downstream collectorCollector 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.