javaadvanced

Advanced Streams — Custom Collectors

Advanced Stream operations: custom collectors, flatMap, reduce, teeing, and parallel streams.

java
import java.util.*;
import java.util.stream.*;
import static java.util.stream.Collectors.*;

public class AdvancedStreams {
    record Transaction(String account, String type, double amount) {}

    public static void main(String[] args) {
        List<Transaction> txns = List.of(
            new Transaction("A", "credit", 100),
            new Transaction("A", "debit", 30),
            new Transaction("B", "credit", 200),
            new Transaction("A", "credit", 50),
            new Transaction("B", "debit", 80)
        );

        // groupingBy + downstream collector
        Map<String, DoubleSummaryStatistics> stats = txns.stream()
            .collect(groupingBy(
                Transaction::account,
                summarizingDouble(Transaction::amount)
            ));
        stats.forEach((acc, s) ->
            System.out.printf("%s: count=%d sum=%.0f avg=%.1f%n",
                acc, s.getCount(), s.getSum(), s.getAverage()));

        // Teeing collector — two results at once
        var result = txns.stream().collect(
            Collectors.teeing(
                filtering(t -> t.type().equals("credit"), summingDouble(Transaction::amount)),
                filtering(t -> t.type().equals("debit"), summingDouble(Transaction::amount)),
                (credits, debits) -> Map.of("credits", credits, "debits", debits, "net", credits - debits)
            ));
        System.out.println(result); // {credits=350.0, debits=110.0, net=240.0}

        // flatMap — flatten nested lists
        List<List<Integer>> nested = List.of(List.of(1, 2), List.of(3, 4), List.of(5));
        List<Integer> flat = nested.stream()
            .flatMap(Collection::stream)
            .toList();

        // reduce with identity
        double total = txns.stream()
            .map(Transaction::amount)
            .reduce(0.0, Double::sum);

        // Collecting to unmodifiable map
        Map<String, Double> balances = txns.stream()
            .collect(groupingBy(
                Transaction::account,
                collectingAndThen(
                    toList(),
                    list -> list.stream()
                        .mapToDouble(t -> t.type().equals("credit") ? t.amount() : -t.amount())
                        .sum()
                )
            ));
        System.out.println(balances); // {A=120.0, B=120.0}
    }
}

Use Cases

  • Complex data aggregation and reporting
  • Financial transaction processing and summarization
  • Multi-dimensional grouping and collection

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.