本文介绍两种常见且实用的嵌套数据结构变换模式——“键轴转置”(Map<X, Map<Y, Z>> → Map<Y, Map<X, Z>>)和“值集反向索引”(Map<X, Set> → Map<Y, Set>),并提供 Java 中清晰、高效、无依赖的实现方案。
本文介绍两种常见且实用的嵌套数据结构变换模式——“键轴转置”(map> → map>)和“值集反向索引”(map> → map>),并提供 java 中清晰、高效、无依赖的实现方案。
在处理多维映射关系(如配置路由、权限矩阵、标签反查、稀疏关联表等)时,常需对嵌套结构进行维度重组。这类操作虽未被 JDK 原生命名,但在函数式编程与数据建模中具有高度通用性:第一种本质是二维映射的坐标轴交换(类比矩阵转置),第二种则是构建值到键的逆向索引(类似倒排索引)。二者均不依赖外部库,可轻量集成于任意 Java 项目。
适用于 Map<K1, Map<K2, V>> → Map<K2, Map<K1, V>> 场景。核心逻辑是遍历原结构的每一层键值对,将内层键(K2)提升为外层主键,原外层键(K1)降为新内层键,并携带对应值(V)。
public static <K1, K2, V> Map<K2, Map<K1, V>> transpose(Map<K1, Map<K2, V>> map) { Map<K2, Map<K1, V>> result = new HashMap<>(); for (Map.Entry<K1, Map<K2, V>> outer : map.entrySet()) { K1 key1 = outer.getKey(); Map<K2, V> innerMap = outer.getValue(); if (innerMap != null) { for (Map.Entry<K2, V> inner : innerMap.entrySet()) { K2 key2 = inner.getKey(); V value = inner.getValue(); result.computeIfAbsent(key2, k -> new HashMap<>()).put(key1, value); } } } return result;}
✅ 示例验证:
输入:Map.of("a", Map.of("X", 1, "Y", 2), "b", Map.of("Y", 3))
输出:Map.of("X", Map.of("a", 1), "Y", Map.of("a", 2, "b", 3))
⚠️ 注意事项:
适用于 Map<K, Set<V>> → Map<V, Set<K>> 场景,典型用于构建“标签→资源列表”、“用户→角色集合”等反向关系。
public static <K, V> Map<V, Set<K>> invertMapOfSets(Map<K, Set<V>> map) { Map<V, Set<K>> result = new HashMap<>(); for (Map.Entry<K, Set<V>> entry : map.entrySet()) { K key = entry.getKey(); Set<V> values = entry.getValue(); if (values != null) { for (V value : values) { result.computeIfAbsent(value, v -> new HashSet<>()).add(key); } } } return result;}
✅ 示例验证:
输入:Map.of("a", Set.of("X", "Y"), "b", Set.of("Y", "Z"))
输出:Map.of("X", Set.of("a"), "Y", Set.of("a", "b"), "Z", Set.of("b"))
⚠️ 注意事项:
这两种变换虽未在标准库中显式命名,却是数据建模中的基础范式: