Collectors

Basic Java
≈ 2 min read

A Collector describes how to assemble a result

Stream.toList() is great when a regular list is needed. But sometimes elements must be joined into a string, grouped by a property, or turned into a Map. For such tasks, the terminal operation collect() is used together with ready-made collectors from the Collectors class.

joining combines strings

String result = Stream.of("Java", "Spring", "SQL")
        .collect(Collectors.joining(", "));

The result value is Java, Spring, SQL. joining also has variants with a prefix and suffix when the final string should be formatted immediately.

groupingBy collects elements by key

groupingBy computes a key for each element and places elements with the same key into one group.

Map<Integer, List<String>> byLength =
        Stream.of("Java", "SQL", "Spring", "HTTP")
                .collect(Collectors.groupingBy(String::length));

The string length becomes the key here. As a result, strings of length 4 are placed into one group, strings of length 3 into another, and so on. The similar partitioningBy operation splits elements into exactly two groups according to the result of a Predicate.

toMap builds a map

Map<String, Integer> lengths =
        Stream.of("Java", "Spring", "SQL")
                .collect(Collectors.toMap(
                        word -> word,
                        String::length
                ));

The first rule creates the key, and the second creates the value. If two elements produce the same key, the simple toMap form cannot choose a winner and throws an exception. For such data, a merge function must be defined in advance.

Map<Integer, String> oneWordByLength =
        Stream.of("Java", "HTTP", "Spring")
                .collect(Collectors.toMap(
                        String::length,
                        word -> word,
                        (left, right) -> left
                ));
Stream.toList() and Collectors.toList() are not complete equivalents. Stream.toList() returns an unmodifiable list. Collectors.toList() does not guarantee a particular implementation or mutability of the result. If a specific collection is required, it is better to express that explicitly.