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&lt;Map.Entry&gt;。 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条目(keyvalue)并通过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 HashMap 内容 [重复]

Java集合之HashMap

Java JSP如何取得HashMap的大小

java调用javascript时,如何将NativeArray或NativeObject转换成java实体或者HashMap,List对象

如何使用 Java 8 Stream 将 Array 转换为 HashMap

如何在 Java 中将 HashMap 转换为 List?