Turning documents-to-tags into tags-to-documents is a flatMap that emits a pair per tag, then a groupingBy that flips it. Map.entry is the cheapest pair type in the JDK and needs no record of its own.
record Doc(String id, List<String> tags) {}
var docs = List.of(new Doc("d1", List.of("java", "streams")),
new Doc("d2", List.of("streams", "kafka")),
new Doc("d3", List.of("java")));
Map<String, List<String>> byTag = docs.stream()
.flatMap(d -> d.tags().stream().map(t -> Map.entry(t, d.id())))
.collect(Collectors.groupingBy(Map.Entry::getKey, TreeMap::new,
Collectors.mapping(Map.Entry::getValue, Collectors.toList())));
byTag.forEach((tag, ids) -> System.out.println(tag + " -> " + ids));
java -> [d1, d3]
kafka -> [d2]
streams -> [d1, d2]
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