Working with Modern Stream Features

1. Using Stream.toList() Method JAVA 16+

AspectDetail
ReturnsUnmodifiable List<T>
Allows nullYes (unlike List.of)
Replacescollect(Collectors.toList())

2. Using Stream.mapMulti() Method JAVA 16+

Example: mapMulti

Stream.of(1, 2, 3, 4, 5)
    .<Integer>mapMulti((n, sink) -> {
        if (n % 2 == 0) {
            sink.accept(n);
            sink.accept(n * n);
        }
    })
    .forEach(System.out::println);    // 2, 4, 4, 16
AspectDetail
SignaturemapMulti(BiConsumer<T, Consumer<R>>)
Use case0..N elements per input without intermediate stream allocation

3. Using Stream.teeing() Collector JAVA 12+

Example: teeing

record Stats(double avg, long count) {}
Stats s = numbers.stream().collect(
    Collectors.teeing(
        Collectors.averagingInt(Integer::intValue),
        Collectors.counting(),
        (avg, count) -> new Stats(avg, count)
    ));
AspectDetail
UseCombine TWO downstream collectors
MergerBiFunction combines results

4. Using Gatherers API JAVA 22+ PREVIEW

AspectDetail
PurposeCustom intermediate operations (parallel-friendly)
Methodstream.gather(gatherer)
Built-inswindowFixed, windowSliding, fold, scan, mapConcurrent

5. Creating Custom Gatherers

Example: Custom gatherer

Gatherer<Integer, ?, Integer> runningMax =
    Gatherer.ofSequential(
        () -> new int[]{ Integer.MIN_VALUE },
        (state, n, downstream) -> {
            state[0] = Math.max(state[0], n);
            return downstream.push(state[0]);
        }
    );
ComponentRole
InitializerPer-thread state
IntegratorPer-element processing
CombinerMerge state (parallel)
FinisherEmit final values

6. Using windowFixed() Gatherer

Example: Fixed window

Stream.of(1,2,3,4,5,6,7)
    .gather(Gatherers.windowFixed(3))
    .forEach(System.out::println);
// [1,2,3], [4,5,6], [7]
AspectDetail
OutputNon-overlapping lists of size n
Last windowMay be smaller

7. Using windowSliding() Gatherer

AspectDetail
OutputOverlapping lists, sliding by 1
Use caseMoving averages, n-grams

8. Using fold() Gatherer

AspectDetail
BehaviorAccumulate to single value with seed
ReturnsStream of one element
Difference from reduceLazy intermediate, composes with stream pipeline

9. Using scan() Gatherer

AspectDetail
BehaviorLike fold but emits each intermediate accumulator
Use caseRunning sums, prefix products

10. Composing Gatherers

MethodUse
g1.andThen(g2)Pipeline composition
ReusableBuild complex transforms from primitives