45

在我的代码中,我Set<Map.Entry<K, V>>从地图创建了一个。现在我想重新创建相同的地图形式,所以我想将HashSet<Map.Entry<K, V>>背面转换为HashMap<K, V>. Java 是否有这样做的本机调用,或者我是否必须循环设置元素并手动构建地图?

4

7 回答 7

70

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

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

IllegalStateException如果遇到重复键,将抛出一个。

于 2015-08-30T10:18:04.880 回答
22

HashSetjava中没有用于和之间直接转换的内置API HashMap,您需要遍历set并使用Entryfill in 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也将反映在Mapset 返回的Map.entrySet是 backup byMap中。见javadoc下文:

Set<Entry<Integer, String>> java.util.Map.entrySet()

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

于 2013-04-19T16:05:38.610 回答
8

相当短的 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,他值得比我更多的功劳

于 2015-02-23T09:51:47.287 回答
8

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

于 2017-07-04T11:34:23.670 回答
4

这些是公共库中的一些toMap实用程序,但不幸的是,它们都没有Set直接支持,所以你需要先做Set#toArray()。(我为尼尔的回答省略了番石榴,这可以说是最好的)

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);
于 2018-03-06T09:16:10.887 回答
3

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>>,你需要一个数组才能使用方法 using 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);

爪哇 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));   // or '-> second' if you need the latests

Java 7 及更早版本

正如现有答案所描述的那样,您所能做的就是对每个迭代进行程序性迭代。

于 2021-03-07T23:20:50.217 回答
1

在具有正确组合器的 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;}););
于 2015-08-29T17:53:05.950 回答