92

I need to copy all keys and values from one A HashMap onto another one B, but not to replace existing keys and values.

Whats the best way to do that?

I was thinking instead iterating the keySet and checkig if it exist or not, I would

Map temp = new HashMap(); // generic later
temp.putAll(Amap);
A.clear();
A.putAll(Bmap);
A.putAll(temp);
Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183
rapadura
  • 5,242
  • 7
  • 39
  • 57

8 Answers8

122

It looks like you are willing to create a temporary Map, so I'd do it like this:

Map tmp = new HashMap(patch);
tmp.keySet().removeAll(target.keySet());
target.putAll(tmp);

Here, patch is the map that you are adding to the target map.

Thanks to Louis Wasserman, here's a version that takes advantage of the new methods in Java 8:

patch.forEach(target::putIfAbsent);
Community
  • 1
  • 1
erickson
  • 265,237
  • 58
  • 395
  • 493
16

Using Guava's Maps class' utility methods to compute the difference of 2 maps you can do it in a single line, with a method signature which makes it more clear what you are trying to accomplish:

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());
}
Tom Tresansky
  • 19,364
  • 17
  • 93
  • 129
8

Just iterate and add:

for(Map.Entry e : a.entrySet())
  if(!b.containsKey(e.getKey())
    b.put(e.getKey(), e.getValue());

Edit to add:

If you can make changes to a, you can also do:

a.putAll(b)

and a will have exactly what you need. (all the entries in b and all the entries in a that aren't in b)

Reverend Gonzo
  • 39,701
  • 6
  • 59
  • 77
6

You can make it in just 1 line if you change maps order in @erickson's solution:

mapWithNotSoImportantValues.putAll( mapWithImportantValues );

In this case you replace values in mapWithNotSoImportantValues with value from mapWithImportantValues with the same keys.

Anatolii Stepaniuk
  • 2,585
  • 1
  • 18
  • 24
5

Java 8 solution using Map#merge

As of you can use Map#merge(K key, V value, BiFunction remappingFunction) which merges a value into the Map using remappingFunction in case the key is already found in the Map you want to put the pair into.

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

The code iterates the newMap entries (key and value) and each one is merged into map through the method merge. The remappingFunction is triggered in case of duplicated key and in that case it says that the former (original) oldValue value will be used and not rewritten.

With this solution, you don't need a temporary Map.


Let's have an example of merging newMap entries into map and keeping the original values in case of the duplicated 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
Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183
2
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);
}}
Jajikanth pydimarla
  • 1,512
  • 13
  • 11
2

With Java 8 there is this API method to accomplish your requirement.

map.putIfAbsent(key, value)

If the specified key is not already associated with a value (or is mapped to null) associates it with the given value and returns null, else returns the current value.

newday
  • 3,842
  • 10
  • 54
  • 79
2

As others have said, you can use putIfAbsent. Iterate over each entry in the map that you want to insert, and invoke this method on the original map:

mapToInsert.forEach(originalMap::putIfAbsent);
whistling_marmot
  • 3,561
  • 3
  • 25
  • 39