Working with Stream Collectors

1. Collecting to List

MethodResult
Collectors.toList()Mutable List (impl-specific)
Collectors.toUnmodifiableList()Immutable
stream.toList() JAVA 16+Unmodifiable, allows null

2. Collecting to Set

MethodResult
Collectors.toSet()HashSet
Collectors.toUnmodifiableSet()Immutable
Collectors.toCollection(TreeSet::new)Custom Set impl

3. Collecting to Map

Example: toMap

Map<Long, User> byId = users.stream()
    .collect(Collectors.toMap(User::id, Function.identity()));

Map<String, Integer> sumByDept = employees.stream()
    .collect(Collectors.toMap(
        Employee::dept,
        Employee::salary,
        Integer::sum                   // merge function for duplicates
    ));
OverloadUse
2 argsThrows on duplicate keys
3 argsMerge function for duplicates
4 argsCustom map supplier

4. Joining Strings

MethodResult
joining()Concat with no delimiter
joining(", ")With delimiter
joining(", ", "[", "]")With prefix/suffix

5. Grouping Elements

Example: groupingBy

Map<String, List<Employee>> byDept = employees.stream()
    .collect(Collectors.groupingBy(Employee::dept));

Map<String, Long> countByDept = employees.stream()
    .collect(Collectors.groupingBy(Employee::dept, Collectors.counting()));

Map<String, Map<String, Long>> nested = employees.stream()
    .collect(Collectors.groupingBy(Employee::dept,
        Collectors.groupingBy(Employee::role, Collectors.counting())));
FormDetail
groupingBy(classifier)Classifier → List
groupingBy(classifier, downstream)Custom downstream collector
groupingBy(classifier, mapFactory, downstream)Custom map type

6. Partitioning Elements

MethodResult
partitioningBy(predicate)Map<Boolean, List<T>>
With downstreampartitioningBy(p, counting())

7. Counting Elements

MethodResult
Collectors.counting()Long total
stream.count()long

8. Finding Statistics

CollectorResult
summingInt/Long/Double(fn)Sum
averagingInt/Long/Double(fn)Mean
minBy(cmp) / maxBy(cmp)Optional
summarizingInt(fn)IntSummaryStatistics (count, sum, min, max, avg)

9. Reducing Elements

Example: reduce

int sum = nums.stream().reduce(0, Integer::sum);
Optional<Integer> max = nums.stream().reduce(Integer::max);
String concat = strs.stream().reduce("", (a, b) -> a + b);
FormReturns
reduce(identity, op)T
reduce(op)Optional<T>
reduce(id, accumulator, combiner)U (parallel-safe)

10. Creating Custom Collectors

ComponentDetail
SupplierNew container
AccumulatorAdd element to container
CombinerMerge two containers (parallel)
FinisherTransform container to result
FactoryCollector.of(supplier, accumulator, combiner, finisher)

11. Collecting to Unmodifiable Collections

MethodResult
toUnmodifiableList()Immutable list
toUnmodifiableSet()Immutable set
toUnmodifiableMap(k, v)Immutable map
Warning: Unmodifiable collectors do NOT allow null elements/keys/values.

12. Using Downstream Collectors

Example: Downstream chaining

Map<String, Set<String>> emailsByDept = employees.stream()
    .collect(Collectors.groupingBy(
        Employee::dept,
        Collectors.mapping(Employee::email, Collectors.toSet())
    ));
CollectorUse
mapping(fn, downstream)Transform before collecting
filtering(p, downstream)Filter before collecting
flatMapping(fn, downstream)Flatten before collecting
collectingAndThen(c, finisher)Post-process result