本文介绍两种常见且实用的嵌套数据结构变换模式——“键轴转置”(Map → Map)和“值集反向索引”(Map → Map),并提供 Java 中清晰、高效、无依赖的实现方案。
本文介绍两种常见且实用的嵌套数据结构变换模式——“键轴转置”(map
在处理多维映射关系(如配置路由、权限矩阵、标签反查、稀疏关联表等)时,常需对嵌套结构进行维度重组。这类操作虽未被 JDK 原生命名,但在函数式编程与数据建模中具有高度通用性:第一种本质是二维映射的坐标轴交换(类比矩阵转置),第二种则是构建值到键的逆向索引(类似倒排索引)。二者均不依赖外部库,可轻量集成于任意 Java 项目。
1. 键轴转置(Transpose)
适用于 Map
public static <k1 k2 v> Map<k2 map v>> transpose(Map<k1 map v>> map) {
Map<k2 map v>> result = new HashMap();
for (Map.Entry<k1 map 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;
}</k2></k2></k1></k2></k1></k2></k1>
✅ 示例验证:
输入: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 为 null,代码已做空安全防护;
- 使用 computeIfAbsent 避免重复创建空 Map,性能优于先 getOrDefault 再 put;
- 返回结果为 HashMap,若需有序结果(如按插入顺序),可替换为 LinkedHashMap。
2. 值集反向索引(Invert Mapping)
适用于 Map
public static <k v> Map<v set>> invertMapOfSets(Map<k set>> map) {
Map<v set>> result = new HashMap();
for (Map.Entry<k set>> 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;
}</v></k></v></k></v></k>
✅ 示例验证:
输入: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"))
⚠️ 注意事项:
- 同样处理 null 值以增强鲁棒性;
- 若需保持插入顺序或自然排序,可分别选用 LinkedHashSet 或 TreeSet 替代 HashSet;
- 该操作本质是“多对多关系的视角翻转”,适用于权限系统、搜索索引、图邻接表转换等场景。
总结
这两种变换虽未在标准库中显式命名,却是数据建模中的基础范式:
- 转置(transpose) 强调维度对称性重构,适用于矩阵式关联;
-
反向索引(invert) 强调关系方向反转,适用于检索优化。
二者均可扩展至流式处理(配合 Collectors.groupingBy + Collectors.flatMapping),但上述 imperative 实现更直观、可控且兼容 Java 8+。建议封装为工具类方法,并根据业务需要添加泛型约束(如 Comparable 要求)或不可变包装(如 Collections.unmodifiableMap)。











