java - 如何将Java hashMap内容的全部放在另一个上,但不替换现有的键和值?
Posted
技术标签:
【中文标题】java - 如何将Java hashMap内容的全部放在另一个上,但不替换现有的键和值?【英文标题】:How to putAll on Java hashMap contents of one to another, but not replace existing keys and values? 【发布时间】:2011-11-03 21:41:10 【问题描述】:我需要将一个 A HashMap 中的所有键和值复制到另一个 B 上,而不是替换现有的键和值。
最好的方法是什么?
我想改为迭代 keySet 并检查它是否存在,我会
Map temp = new HashMap(); // generic later
temp.putAll(Amap);
A.clear();
A.putAll(Bmap);
A.putAll(temp);
【问题讨论】:
【参考方案1】:看起来你愿意创建一个临时的Map
,所以我会这样做:
Map tmp = new HashMap(patch);
tmp.keySet().removeAll(target.keySet());
target.putAll(tmp);
这里,patch
是您要添加到 target
地图的地图。
感谢Louis Wasserman,,这是一个利用 Java 8 中新方法的版本:
patch.forEach(target::putIfAbsent);
【讨论】:
在这种情况下,您无需执行removeAll
,因为无论如何它们都会被覆盖。
@Reverend Gonzo:被什么覆盖了?
@luksmir 不,这将删除应该保留的现有条目。
嗨!为什么 mapWithValues.putAll(mapWithAnotherValues) 不起作用?
@erickson 更紧凑的 Java 8 版本:patch.forEach(target::putIfAbsent)
。【参考方案2】:
使用 Guava 的 Maps 类的实用方法来计算 2 个映射的差异,您可以在一行中完成,方法签名可以更清楚地说明您要完成的工作:
public static void main(final String[] args)
// Create some maps
final Map<Integer, String> map1 = new HashMap<Integer, String>();
map1.put(1, "Hello");
map1.put(2, "There");
final Map<Integer, String> map2 = new HashMap<Integer, String>();
map2.put(2, "There");
map2.put(3, "is");
map2.put(4, "a");
map2.put(5, "bird");
// Add everything in map1 not in map2 to map2
map2.putAll(Maps.difference(map1, map2).entriesOnlyOnLeft());
【讨论】:
【参考方案3】:只需迭代并添加:
for(Map.Entry e : a.entrySet())
if(!b.containsKey(e.getKey())
b.put(e.getKey(), e.getValue());
编辑添加:
如果您可以对 a 进行更改,您也可以这样做:
a.putAll(b)
a 将拥有您所需要的一切。 (b
中的所有条目以及a
中不在b
中的所有条目)
【讨论】:
1.)entrySet()
返回 Set<Map.Entry>
。 2.) contains(...)
for java.util.Map
没有方法。
没有更聪明的方法吗?像 Collections 实用程序一样吗?我讨厌到处都是 for 循环。
@AntonioP:到处都是 for 循环?有一个 for 循环,它尽可能简单。
+1 然后,我认为,当 Maps 不使用原始类型时才有效。让自己对 Map.Entry 有点糊涂了 :-)
@Reverend Gonzo,啊,在代码的其他地方。 :) 不会 .putAll 替换 a 的现有键和值吗?从这个意义上说,这似乎是最直接的方式。【参考方案4】:
如果您在@erickson 的解决方案中更改地图顺序,只需一行即可完成:
mapWithNotSoImportantValues.putAll( mapWithImportantValues );
在这种情况下,您将 mapWithNotSoImportantValues 中的值替换为具有相同键的 mapWithImportantValues 中的值。
【讨论】:
【参考方案5】:使用Map#merge
的Java 8 解决方案
从java-8 开始,您可以使用Map#merge(K key, V value, BiFunction remappingFunction)
,它使用remappingFunction
将一个值合并到Map
中,以防在您想要放入该对的Map
中找到密钥。
// using lambda
newMap.forEach((key, value) -> map.merge(key, value, (oldValue, newValue) -> oldValue));
// using for-loop
for (Map.Entry<Integer, String> entry: newMap.entrySet())
map.merge(entry.getKey(), entry.getValue(), (oldValue, newValue) -> oldValue);
代码迭代newMap
条目(key
和value
)并通过merge
方法将每个条目合并到map
中。 remappingFunction
在重复键的情况下被触发,在这种情况下,它表示将使用前(原始)oldValue
值而不是重写。
使用此解决方案,您不需要临时的Map
。
让我们举一个例子,将newMap
条目合并到map
中,并在出现重复antry 的情况下保留原始值。
Map<Integer, String> newMap = new HashMap<>();
newMap.put(2, "EVIL VALUE"); // this will NOT be merged into
newMap.put(4, "four"); // this WILL be merged into
newMap.put(5, "five"); // this WILL be merged into
Map<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
newMap.forEach((k, v) -> map.merge(k, v, (oldValue, newValue) -> oldValue));
map.forEach((k, v) -> System.out.println(k + " " + v));
1 one 2 two 3 three 4 four 5 five
【讨论】:
【参考方案6】:public class MyMap
public static void main(String[] args)
Map<String, String> map1 = new HashMap<String, String>();
map1.put("key1", "value1");
map1.put("key2", "value2");
map1.put("key3", "value3");
map1.put(null, null);
Map<String, String> map2 = new HashMap<String, String>();
map2.put("key4", "value4");
map2.put("key5", "value5");
map2.put("key6", "value6");
map2.put("key3", "replaced-value-of-key3-in-map2");
// used only if map1 can be changes/updates with the same keys present in map2.
map1.putAll(map2);
// use below if you are not supposed to modify the map1.
for (Map.Entry e : map2.entrySet())
if (!map1.containsKey(e.getKey()))
map1.put(e.getKey().toString(), e.getValue().toString());
System.out.println(map1);
【讨论】:
【参考方案7】:在 Java 8 中,有这个 API 方法可以满足您的要求。
map.putIfAbsent(key, value)
如果指定的键尚未与值关联(或映射为 null),则将其与给定值关联并返回 null,否则返回当前值。
【讨论】:
我们可以有 putAllIfAbsent 吗?这就是我需要的?【参考方案8】:正如其他人所说,您可以使用putIfAbsent
。遍历地图中要插入的每个条目,并在原始地图上调用此方法:
mapToInsert.forEach(originalMap::putIfAbsent);
【讨论】:
以上是关于java - 如何将Java hashMap内容的全部放在另一个上,但不替换现有的键和值?的主要内容,如果未能解决你的问题,请参考以下文章
java调用javascript时,如何将NativeArray或NativeObject转换成java实体或者HashMap,List对象