The inverse of merging. groupingBy on the discriminator splits one mixed feed into the lists each downstream handler wants, and the group count tells you how many handlers were actually needed.
record Event(String type, String id) {}
var events = List.of(new Event("order", "o1"), new Event("refund", "r1"),
new Event("order", "o2"), new Event("audit", "a1"),
new Event("refund", "r2"));
Map<String, List<String>> routed = events.stream()
.collect(Collectors.groupingBy(Event::type, TreeMap::new,
Collectors.mapping(Event::id, Collectors.toList())));
routed.forEach((type, ids) -> System.out.println(type + " -> " + ids));
System.out.println("routed " + events.size() + " events to " + routed.size() + " handlers");
audit -> [a1]
order -> [o1, o2]
refund -> [r1, r2]
routed 5 events to 3 handlers
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