在我的代码中的某个时刻,我从地图创建了一个
Set<Map.Entry<K, V>>
。现在我想重新创建相同的地图表单,因此我想将 HashSet<Map.Entry<K, V>>
转换回 HashMap<K, V>
。 Java 是否有执行此操作的本机调用,或者我是否必须循环遍历集合元素并手动构建映射?
更简单的 Java-8 解决方案,涉及
Collectors.toMap
:
Map<Integer, String> mapFromSet = set.stream()
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
如果遇到重复的键,将会抛出
IllegalStateException
。
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操作。
相当短的 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,他比我更值得赞扬
从 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 带来了 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
toMap
实用程序,但不幸的是它们都不直接支持
Set
,因此您需要先执行 Set#toArray()
。我遗漏了Guava
,因为Neil的答案可以说是最好的。 Apache Commons Lang 的
ArrayUtils.toMapMap<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);
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;}););
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 循环中进行迭代。然而,它不包括我在这里展示的类型转换。