将 Set<Map.Entry<K, V>> 转换为 HashMap<K, V>

问题描述 投票:0回答:8

在我的代码中的某个时刻,我从地图创建了一个

Set<Map.Entry<K, V>>
。现在我想重新创建相同的地图表单,因此我想将
HashSet<Map.Entry<K, V>>
转换回
HashMap<K, V>
。 Java 是否有执行此操作的本机调用,或者我是否必须循环遍历集合元素并手动构建映射?

java dictionary set
8个回答
88
投票

更简单的 Java-8 解决方案,涉及

Collectors.toMap
:

Map<Integer, String> mapFromSet = set.stream()
    .collect(Collectors.toMap(Entry::getKey, Entry::getValue));

如果遇到重复的键,将会抛出

IllegalStateException


23
投票

java中没有内置API可以直接在

HashSet
HashMap
之间进行转换,需要迭代set并使用
Entry
填充map。

一种方法:

Map<Integer, String> map = new HashMap<Integer, String>();
    //fill in map
    Set<Entry<Integer, String>> set = map.entrySet();

    Map<Integer, String> mapFromSet = new HashMap<Integer, String>();
    for(Entry<Integer, String> entry : set)
    {
        mapFromSet.put(entry.getKey(), entry.getValue());
    }

虽然这里的目的是什么,但如果您对

Set
进行任何更改,也会反映在
Map
中,因为
Map.entrySet
返回的设置由
Map
备份。请参阅下面的
javadoc

设置> java.util.Map.entrySet()

返回此映射中包含的映射的集合视图。套装是 由地图支持,因此对地图的更改会反映在集合中,并且 反之亦然。如果在对集合进行迭代时修改映射 正在进行中(除非通过迭代器自己的删除操作,或者 通过对返回的映射条目进行 setValue 操作 迭代器)迭代的结果是未定义的。该套装支持 元素删除,从地图中删除相应的映射, 通过 Iterator.remove、Set.remove、removeAll、retainAll 和clear 运营。不支持add或addAll操作。


9
投票

相当短的 Java 8 解决方案。可以应对重复的按键。

    Map<Integer, String> map = new HashMap<>();
    //fill in map
    Set<Map.Entry<Integer, String>> set = map.entrySet();
    Map<Integer, String> mapFromSet = set.stream().collect(Collectors.toMap(Entry::getKey,
      Entry::getValue,
      (a,b)->b));

编辑:感谢shmosel,他比我更值得赞扬


9
投票

从 Guava 19 开始,您可以使用

ImmutableMap.copyOf(Iterable<Map.Entry<K,V>>)


6
投票

Java 9+ 没有抑制警告

从 Java 9 版本开始,集合接口提供了一堆方便的静态方法,允许您内联做很多事情。有一个使用静态方法

Map.ofEntries(Map.Entry... entries)
的内置解决方案,它创建了一个不可变的映射。

Map<Integer,String> map = Map.ofEntries(
        new SimpleEntry<>(1, "one"), 
        new SimpleEntry<>(2, "two"), 
        new SimpleEntry<>(3, "three"));

请注意,还可以使用

Map.entry(K, V)
方法,这使得一切变得不那么冗长。

Map<Integer,String> map2 = Map.ofEntries(
        Map.entry(1, "one"), 
        Map.entry(2, "two"), 
        Map.entry(3, "three"));

假设你有

Set<Map.Entry<K, V>>
,你需要一个数组来使用使用
Set#toArray(T[])
的方法。由于禁止创建通用数组,因此需要显式转换,这是此解决方案的唯一缺点。

Set<Map.Entry<Integer,String>> set = ...
Entry<Integer, String>[] entries = set.<Entry<Integer,String>>toArray(Entry[]::new);
Map<Integer,String> map = Map.ofEntries(entries);

Java 8

Java 8 带来了 Stream API,使用起来非常简单

Collectors.toMap(keyFn, valueFn)

Set<Map.Entry<Integer,String>> set = ...
Map<Integer,String> map = set.stream()
    .collect(Collectors.toMap(
            Entry::getKey,
            Entry::getValue));

为了避免在存在两个

Map.Entry
具有字典中禁止的相同键的情况下出现错误行为,请使用
Collectors.toMap(keyFn, valueFn, mergeFn)
。返回
first
second
,具体取决于您是否要保留为某个键找到的第一个值或最新值。

Map<Integer,String> map = set.stream()
    .collect(Collectors.toMap(
            Entry::getKey, 
            Entry::getValue,
            (first, second) -> first));  // if you need the 1st occurrence
         // (first, second) -> second)); // if you need the last occurrence

Java 7 及更早版本

您所能做的就是按照“现有答案”描述的那样对每次迭代进行程序。


5
投票
toMap

实用程序,但不幸的是它们都不直接支持

Set
,因此您需要先执行
Set#toArray()
我遗漏了

Guava

,因为Neil的答案可以说是最好的。 Apache Commons Lang 的

ArrayUtils.toMap

Map<Object, Object> map = ArrayUtils.toMap(entrySet.toArray()); // to recover the type... @SuppressWarnings("unchecked") Map<K, V> typedMap = (Map<K, V>)(Map<?, ?>)map;

Apache Commons Collections' 
MapUtils.putAll

Map<K, V> map = MapUtils.putAll(new HashMap<K, V>(), entrySet.toArray());

Java 9 的 
Map.ofEntries

// convert to array and recover the type... @SuppressWarnings("unchecked") Map<K, V> map = Map.ofEntries(entrySet.toArray(new Map.Entry[0])); // You need to copy again if you want a mutable one Map<K, V> hashmap = new HashMap<>(map);



1
投票

Map<Integer, String> map = new HashMap<>(); //fill in map Set<Map.Entry<Integer, String>> set = map.entrySet(); Map<Integer, String> mapFromSet =set.stream().collect(HashMap::new,(t, u) -> t.put(u.getKey(), u.getValue()), (Map mapToReturn, Map otherMap) -> { otherMap.entrySet().forEach((Map.Entry entry) -> { mapToReturn.put(entry.getKey(),entry.getValue()); }); return mapToReturn;}););



0
投票

public static Map<String, Integer> intersect(Map<String, Integer> map_one, Map<String, Integer> map_two) {     Set<Map.Entry<String, Integer>> set_one = map_one.entrySet(); //Map one now a set     Set<Map.Entry<String, Integer>> set_two = map_two.entrySet(); //Map two now a set     set_one.retainAll(set_two); //a math intersection operation set_one and set_two whose contents are the intersection of the two sets     Map<String, Integer> map_retur = new HashMap<>(); //instantiation  of a new Map object     Iterator i = set_one.iterator(); //instantiation of an iterator       while(i.hasNext())       {          Map.Entry me = (Map.Entry)i.next(); // instantiation of Map.Entry as me and convert i into that Map.Entry          map_retur.put((String)me.getKey(), (Integer)me.getValue()); // store each key/value pair into the Map as required       }     return map_retur; // returned value is a map with only the intersections }

谢谢参考:

https://www.tutorialspoint.com/java/java_mapentry_interface.html 了解如何在 foreach 循环中进行迭代。然而,它不包括我在这里展示的类型转换。

© www.soinside.com 2019 - 2024. All rights reserved.