Collectors.groupingBy() patterns¶
Collectors.groupingBy() is a utility method in Java 8 used to group elements of a Stream by a specific classification function^[600-developer__java__java8__java8.md].
Basic Grouping¶
The simplest form of groupingBy accepts a classifier function that determines the keys of the resulting map^[600-developer__java__java8__java8.md].
The default return type for this basic grouping is a Map<K, List<V>>, where the values are lists of items matching each key^[600-developer__java__java8__java8.md].
// Syntax
Map<Integer, List<Sample>> result = stream.collect(Collectors.groupingBy(element -> element.key));
Multi-level Grouping¶
It is possible to perform nested grouping by passing a second groupingBy collector as the downstream argument^[600-developer__java__java8__java8.md]. This creates a two-level map structure^[600-developer__java__java8__java8.md].
// Returns Map<Integer, Map<Integer, List<Sample>>>
Map<Integer, Map<Integer, List<Sample>>> nested = samples.stream()
.collect(Collectors.groupingBy(
x -> x.type,
Collectors.groupingBy(x -> x.score)
));
Statistical Grouping Patterns¶
The groupingBy collector is often combined with other Collectors utility methods to perform calculations on grouped data^[600-developer__java__java8__java8.md].
Summation¶
To sum an integer field within groups, use Collectors.summingInt (or summingLong/summingDouble)^[600-developer__java__java8__java8.md].
Map<Integer, Integer> sums = samples.stream()
.collect(Collectors.groupingBy(
x -> x.type,
Collectors.summingInt(x -> x.score)
));
Maximum Value¶
To find the maximum element in each group based on a comparator, use Collectors.maxBy^[600-developer__java__java8__java8.md]. The result is a Map<K, Optional<V>>^[600-developer__java__java8__java8.md].
Map<Integer, Optional<Sample>> maxValues = samples.stream()
.collect(Collectors.groupingBy(
x -> x.type,
Collectors.maxBy((x, y) -> x.score - y.score)
));
Reducing (Mapping and Folding)¶
You can apply a reduction operation (such as summation) to a specific property of the grouped elements^[600-developer__java__java8__java8.md]. This pattern typically chains Collectors.mapping with Collectors.reducing^[600-developer__java__java8__java8.md].
Map<Integer, Optional<Integer>> reduced = samples.stream()
.collect(Collectors.groupingBy(
x -> x.type,
Collectors.mapping(
x -> x.score,
Collectors.reducing((x, y) -> x + y)
)
));
Sources¶
^[600-developer__java__java8__java8.md]