Multi-stream: two-level grouping where the inner key comes from another list

Nested groupingBy builds a map of maps, and nothing stops the inner classifier from reaching into a joined index. Both levels use TreeMap so the report is reproducible.

Code
record Product(String sku, String category) {}
record Sale(String sku, String region, double amount) {}

var products = List.of(new Product("S1", "pens"), new Product("S2", "books"), new Product("S3", "pens"));
var sales = List.of(new Sale("S1", "east", 10.0), new Sale("S2", "east", 50.0),
                    new Sale("S3", "west", 20.0), new Sale("S1", "west", 5.0));

Map<String, String> categoryOf = products.stream()
        .collect(Collectors.toMap(Product::sku, Product::category));

Map<String, Map<String, Double>> byRegionThenCategory = sales.stream()
        .collect(Collectors.groupingBy(Sale::region, TreeMap::new,
                 Collectors.groupingBy(s -> categoryOf.get(s.sku()), TreeMap::new,
                 Collectors.summingDouble(Sale::amount))));

byRegionThenCategory.forEach((region, m) -> System.out.println(region + " " + m));
Output
east {books=50.0, pens=10.0}
west {pens=25.0}
Advertisement
More in JAVA

Run this yourself in the Online Java Compiler, spin up a live REST API in the API Sandbox, or practise with Java interview questions.

Published 2026-09-20

© Java Coding Hub · About · Contact · Privacy · Terms