Streams: nested groupingBy builds a map of maps

A grouping collector can be the downstream of another grouping, which produces a two-level index in one pass.

Code
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));
Output
IN {FAILED=20, PAID=150}
UK {PAID=70}
Advertisement

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