Java8 Stream操作嵌套Map(Map<String, List<Map<String, String>>>)技术问询
Alright, let's figure out how to handle this nested Map transformation using Java 8 Streams. From your description, it looks like you want to reverse the original mapping—instead of having outer keys pointing to lists of inner Maps, you want each inner Map mapped to all the outer keys it appears under. Here's a step-by-step breakdown with code examples:
First, let's recreate the nested Map you described to use as our test data:
import java.util.*; import java.util.stream.Collectors; public class NestedMapStreamExample { public static void main(String[] args) { // Define inner maps (M1, M2, M3, M4, M5) Map<String, String> m1 = Map.of("id", "M1"); Map<String, String> m2 = Map.of("id", "M2"); Map<String, String> m3 = Map.of("id", "M3"); Map<String, String> m4 = Map.of("id", "M4"); Map<String, String> m5 = Map.of("id", "M5"); // Build the original nested Map Map<String, List<Map<String, String>>> inputMap = new HashMap<>(); inputMap.put("1", Arrays.asList(m1, m1, m3)); inputMap.put("2", Arrays.asList(m1, m2, m3)); inputMap.put("3", Collections.singletonList(m4)); inputMap.put("4", Arrays.asList(m2, m5));
To get each inner Map paired with its associated outer keys, we'll use flatMap to break down the nested structure, then groupingBy to aggregate the results:
// Reverse the mapping: Map<Map<String,String>, List<String>> Map<Map<String, String>, List<String>> reversedMap = inputMap.entrySet() .stream() // Flatten each outer entry into (innerMap, outerKey) pairs .flatMap(outerEntry -> outerEntry.getValue().stream() .map(innerMap -> new AbstractMap.SimpleEntry<>(innerMap, outerEntry.getKey()))) // Group by innerMap, collecting all corresponding outer keys .collect(Collectors.groupingBy( Map.Entry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.toList()) )); // Test output: Check outer keys for M1 System.out.println("Outer keys for M1: " + reversedMap.get(m1)); // Output: [1, 1, 2]
If you don't want duplicate outer keys (like the two "1"s for M1), modify the collector to use a set first, then convert back to a list:
// Reverse mapping with unique outer keys Map<Map<String, String>, List<String>> reversedMapUnique = inputMap.entrySet() .stream() .flatMap(outerEntry -> outerEntry.getValue().stream() .map(innerMap -> new AbstractMap.SimpleEntry<>(innerMap, outerEntry.getKey()))) .collect(Collectors.groupingBy( Map.Entry::getKey, Collectors.mapping( Map.Entry::getValue, Collectors.collectingAndThen(Collectors.toSet(), ArrayList::new) ) )); // Test output: Unique outer keys for M1 System.out.println("Unique outer keys for M1: " + reversedMapUnique.get(m1)); // Output: [1, 2] } }
- Inner Map as Key: For this to work correctly, your inner Maps must have proper
equals()andhashCode()implementations. The default implementations forHashMap,LinkedHashMap, and the immutableMap.of()entries work perfectly here, as they compare all key-value pairs. - FlatMap Explained: The
flatMapstep takes each outer entry (e.g., "1" -> [M1, M1, M3]) and splits it into individual (innerMap, outerKey) pairs. This turns the nested structure into a flat stream of entries we can easily group. - Collector Flexibility: You can adjust the collector to fit other needs—for example, using
Collectors.joining(", ")if you want a comma-separated string of outer keys instead of a list.
内容的提问来源于stack exchange,提问作者Pankaj Singhal

