簡體   English   中英

你怎么反映地圖 <v1, Set<v2> &gt;到地圖 <v2, Set<v1> &gt;在Java中使用stream()

[英]How do you invert Map<v1, Set<v2>> to Map<v2, Set<v1>> in Java with stream()

我有一個Map對象Map<t1, Set<t2>> ,我想進入集合並將集合中的t2轉換為新地圖的鍵。 原始鍵t1將是地圖的新值。
例如,給定一個包含兩個條目的地圖

{key1: [a, b, c], key2: [c, d]}

得到的地圖將是

{a: [key1], b: [key1], c: [key1, key2], d: [key2]}

[]表示在上面的例子中設置。

Java 8:

map.entrySet()
        .stream()
        .flatMap(e -> e.getValue()
                .stream()
                .map(v -> new SimpleEntry<>(v, e.getKey())))
        .collect(Collectors.groupingBy(Entry::getKey,
                Collectors.mapping(Entry::getValue, Collectors.toSet())))

番石榴

Multimaps.asMap(map.entrySet()
        .stream()
        .collect(ImmutableSetMultimap.flatteningToImmutableSetMultimap(
                Entry::getKey, e -> e.getValue().stream()))
        .inverse())

StreamEx

EntryStream.of(map)
        .flatMapValues(Set::stream)
        .invert()
        .grouping(Collectors.toSet())

一種方法可能是:

private static <T1,T2> Map<T1, Set<T2>> invertMap(Map<T2, Set<T1>> data) {
        Map<T1, Set<T2>> output = data.entrySet().stream().collect(() -> new HashMap<T1, Set<T2>>(),
                (mapLeft, leftEntry) -> {
                    for (T1 i : leftEntry.getValue()) {

                        Set<T2> values = mapLeft.get(i);
                        if (values == null)
                            values = new HashSet<>();

                        values.add(leftEntry.getKey());
                        mapLeft.put(i, values);
                    }
                }, (mapLeft, mapRight) -> mapLeft.putAll(mapRight));
        return output;
    }

一種方法可以是 -

Map<V1,Set<V2>> inputHashMap = new HashMap<>(); // initialized with your input
Map<V2,Set<V1>> outputHashMap = new HashMap<>();

inputHashMap.forEach((val, keys) -> keys.forEach(key -> {
    if (outputHashMap.containsKey(key)) {
        outputHashMap.get(key).add(val);
    } else {
        outputHashMap.put(key, new HashSet<>() {{
            add(val);
        }});
    }
}));

使用流(可能適合在流上使用parallel()進行並行處理)

Map<String, Set<String>> inMap = new HashMap<>();
inMap.put("key1", new HashSet<>(Arrays.asList("a", "b", "c")));
inMap.put("key2", new HashSet<>(Arrays.asList("c", "d")));

Map<String, Set<String>> outMap = inMap.entrySet().stream().collect(
    HashMap::new,
    (m, e) -> e.getValue().forEach(v -> m.computeIfAbsent(v, ignore -> new HashSet<>())
                                         .add(e.getKey())),
    (m1, m2) -> m2.forEach((key, value) -> m1.merge(key, value,
                                           (s1, s2) -> { s1.addAll(s2); return s1; })));

System.out.println(outMap);
// {a=[key1], b=[key1], c=[key1, key2], d=[key2]}

當然for循環舊學校更清潔

Map<String, Set<String>> outMap = new HashMap<>();

for (Entry<String, Set<String>> e : inMap.entrySet())
  for (String v : e.getValue())
    outMap.computeIfAbsent(v, key -> new HashSet<>()).add(e.getKey());

減少LOC

Map<String, Set<String>> outMap = new HashMap<>();
inMap.forEach((k, v) -> v.forEach(e ->
  outMap.computeIfAbsent(e, __ -> new HashSet<>()).add(k)));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM