You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌套数据结构两类通用转换需求:求JVM生态实现方案

两类嵌套数据结构转换的名称与JVM语言实现

转换名称定义

  • 第一类:嵌套Map转置(Transpose Nested Map),你猜测的“转置”是准确的,把嵌套Map看作X行Y列的矩阵,转置后就是Y行X列的矩阵。
  • 第二类:多值映射反转(Inverse Multimap),将单键多值的映射反转成单值多键的映射。

Java实现方案

1. 嵌套Map转置

原生Stream实现

import java.util.Map;
import java.util.stream.Collectors;

public class MapTransposer {
    public static <X, Y, Z> Map<Y, Map<X, Z>> transposeNestedMap(Map<X, Map<Y, Z>> input) {
        return input.entrySet().stream()
                .flatMap(xEntry -> xEntry.getValue().entrySet().stream()
                        .map(yEntry -> Map.entry(yEntry.getKey(), Map.entry(xEntry.getKey(), yEntry.getValue()))))
                .collect(Collectors.groupingBy(
                        Map.Entry::getKey,
                        Collectors.toMap(
                                nestedEntry -> nestedEntry.getValue().getKey(),
                                nestedEntry -> nestedEntry.getValue().getValue()
                        )
                ));
    }

    // 测试示例
    public static void main(String[] args) {
        Map<String, Map<String, Integer>> input = Map.of(
                "a", Map.of("X", 1, "Y", 2),
                "b", Map.of("Y", 3)
        );
        Map<String, Map<String, Integer>> output = transposeNestedMap(input);
        System.out.println(output);
        // 输出:{X={a=1}, Y={a=2, b=3}}
    }
}

第三方库方案(Guava)

Guava可借助Multimap间接实现转置:

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;

import java.util.Map;

public class GuavaMapTranspose {
    public static <X, Y, Z> Map<Y, Map<X, Z>> transposeWithGuava(Map<X, Map<Y, Z>> input) {
        Multimap<Y, Map.Entry<X, Z>> tempMultimap = ArrayListMultimap.create();
        input.forEach((x, yzMap) ->
                yzMap.forEach((y, z) -> tempMultimap.put(y, Map.entry(x, z))));

        return Multimaps.asMap(tempMultimap).entrySet().stream()
                .collect(Map::ofEntries,
                        (map, entry) -> map.put(entry.getKey(),
                                entry.getValue().stream().collect(Map::ofEntries,
                                        (innerMap, e) -> innerMap.put(e.getKey(), e.getValue()),
                                        Map::putAll)),
                        Map::putAll);
    }
}

2. 多值映射反转

原生Stream实现

import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class InvertMultiMap {
    public static <X, Y> Map<Y, Set<X>> invertMultiMap(Map<X, Set<Y>> input) {
        return input.entrySet().stream()
                .flatMap(xEntry -> xEntry.getValue().stream()
                        .map(y -> Map.entry(y, xEntry.getKey())))
                .collect(Collectors.groupingBy(
                        Map.Entry::getKey,
                        Collectors.mapping(
                                Map.Entry::getValue,
                                Collectors.toSet()
                        )
                ));
    }

    // 测试示例
    public static void main(String[] args) {
        Map<String, Set<String>> input = Map.of(
                "a", Set.of("X", "Y"),
                "b", Set.of("Y", "Z")
        );
        Map<String, Set<String>> output = invertMultiMap(input);
        System.out.println(output);
        // 输出:{X=[a], Y=[a, b], Z=[b]}
    }
}

第三方库方案(Guava)

Guava的Multimap原生支持反转,是最便捷的方案:

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;

import java.util.Map;
import java.util.Set;

public class GuavaInvertMultiMap {
    public static <X, Y> Map<Y, Set<X>> invertWithGuava(Map<X, Set<Y>> input) {
        Multimap<X, Y> multimap = HashMultimap.create();
        input.forEach(multimap::putAll);
        return Multimaps.asMap(Multimaps.invertFrom(multimap, HashMultimap.create()));
    }
}

Groovy实现方案

Groovy语法糖可大幅简化代码:

1. 嵌套Map转置

def transposeNestedMap(Map input) {
    input.collectMany { x, yzMap ->
        yzMap.collect { y, z -> [y, [x, z]] }
    }.groupBy { it[0] }.collectEntries { y, entries ->
        [y, entries.collectEntries { [it[1][0], it[1][1]] }]
    }
}

// 测试
def input = [a: [X:1, Y:2], b: [Y:3]]
println transposeNestedMap(input) // 输出:[X:[a:1], Y:[a:2, b:3]]

2. 多值映射反转

def invertMultiMap(Map input) {
    input.collectMany { x, ys -> ys.collect { y -> [y, x] } }
         .groupBy { it[0] }
         .collectEntries { y, xs -> [y, xs*.getAt(1) as Set] }
}

// 测试
def input = [a: ['X', 'Y'] as Set, b: ['Y', 'Z'] as Set]
println invertMultiMap(input) // 输出:[X:[a], Y:[a, b], Z:[b]]

Clojure实现方案

Clojure核心库提供函数式简洁实现:

1. 嵌套Map转置

(defn transpose-nested-map [input]
  (->> input
       (mapcat (fn [[x yz-map]]
                 (map (fn [[y z]] [y [x z]]) yz-map)))
       (group-by first)
       (reduce (fn [acc [y entries]]
                 (assoc acc y (into {} (map (fn [[_ [x z]]] [x z]) entries))))
               {})))

;; 测试
(def input {"a" {"X" 1, "Y" 2}, "b" {"Y" 3}})
(println (transpose-nested-map input)) ; 输出:{"X" {"a" 1}, "Y" {"a" 2, "b" 3}}

2. 多值映射反转

(defn invert-multi-map [input]
  (->> input
       (mapcat (fn [[x ys]] (map (fn [y] [y x]) ys)))
       (group-by first)
       (reduce (fn [acc [y xs]]
                 (assoc acc y (set (map second xs))))
               {})))

;; 测试
(def input {"a" #{"X" "Y"}, "b" #{"Y" "Z"}})
(println (invert-multi-map input)) ; 输出:{"X" #{"a"}, "Y" #{"a" "b"}, "Z" #{"b"}}

内容的提问来源于stack exchange,提问作者Ionut Bilica

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 16:35:31