A grouping collector can be the downstream of another grouping, which produces a two-level index in one pass.
record Txn(String country, String status, int amount) {}
var txns = List.of(new Txn("IN", "PAID", 100), new Txn("IN", "FAILED", 20),
new Txn("IN", "PAID", 50), new Txn("UK", "PAID", 70));
Map<String, Map<String, Integer>> report = txns.stream().collect(
Collectors.groupingBy(Txn::country, TreeMap::new,
Collectors.groupingBy(Txn::status, TreeMap::new,
Collectors.summingInt(Txn::amount))));
report.forEach((country, byStatus) -> System.out.println(country + " " + byStatus));
IN {FAILED=20, PAID=150}
UK {PAID=70}
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-07-30