转换Set <map.entry <k,v =“”>&gt;到HashMap <k,v =“”> </k,> </map.entry <k,>

时间:2013-04-19 15:57:53

标签: java map set

在我的代码中,我从地图创建了Set<Map.Entry<K, V>>。现在我想重新创建相同的地图表单,因此我想将HashSet<Map.Entry<K, V>>转换回HashMap<K, V>。 Java是否有本机调用,或者我是否需要遍历set元素并手动构建映射?

7 个答案:

答案 0 :(得分:38)

涉及Collectors.toMap的简单Java-8解决方案:

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

如果遇到重复密钥,则会抛出IllegalStateException

答案 1 :(得分:21)

java中没有用于HashSetHashMap之间直接转换的内置API,您需要遍历集并使用Entry填充地图。

一种方法:

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进行备份。请参阅下面的{{1}}:

  

设置&lt; Entry&lt;整数,字符串&gt;&gt; java.util.Map.entrySet()

     

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

答案 2 :(得分:5)

相当简短的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,我应该获得比此更多的信任

答案 3 :(得分:5)

从Guava 19开始,您可以使用ImmutableMap.copyOf(Iterable<Map.Entry<K,V>>)

答案 4 :(得分:3)

这些是常见库中的一些toMap实用程序,但遗憾的是,它们都不直接支持Set,因此您需要先执行Set#toArray()。 (我遗漏了Guava Neil's answer,这可能是最好的)

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;

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);

答案 5 :(得分:2)

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 带来了使用 Collectors.toMap(keyFn, valueFn) 非常简单的 Stream API。

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)。返回 firstsecond,具体取决于您是要保留为某个键找到的第一个值还是最新的值。

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

Java 7 及更早版本

所有,您可以做的就是对每次迭代进行程序化,如 existing answer 描述。

答案 6 :(得分:0)

在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(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;}););