Collectors, groupingBy, and Parallel Streams
Collectors, groupingBy, and Parallel Streams
Collectors turn streams back into useful structures, and groupingBy builds maps of grouped data in one line. Parallel streams can speed up large data sets, but only when you respect the rules that keep them correct, so the last topic here is about discipline as much as technique.
Collectors basics
The Collectors utility class provides ready-made collectors for the common terminal operations. Collectors.toList(), toSet(), toMap(), and the newer Stream.toList() materialize results. The real power appears with downstream collectors that post-process each group.
Map<String, List<Employee>> byDept = employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));
Map<String, Long> countByDept = employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment,
Collectors.counting()));
groupingBy and downstream collectors
groupingBy classifies elements by a function and groups them into a Map. The second argument lets you feed each group through another collector, enabling patterns like counting per group, summing salaries per department, or mapping names. Pair it with mapping, summingInt, and collectingAndThen for sophisticated reports in a single pass over the data.
Parallel streams
parallelStream() splits the source across a shared fork-join pool. It only pays off for large collections and CPU-bound work, since splitting and merging add overhead. Correct parallel pipelines must be stateless: operations must not mutate shared state and should use thread-safe or immutable structures.
When to avoid them
Avoid parallel streams for small sources, when ordering matters and you rely on encounter order, or when your lambdas access non-thread-safe resources like file handles or shared maps. When in doubt, measure; parallel is never automatic performance.
Key Points
- Collectors materialize stream results into collections and values.
groupingBywith downstream collectors does grouped aggregation in one pass.toMapandtoListcover most materialization needs.- Parallel streams help only with large, CPU-bound, stateless pipelines.
- Measure before choosing parallel over sequential streams.