How to putAll on Java hashMap contents of one to another, but not replace existing keys and values?

JavaDictionaryHashmap

Java Problem Overview


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

Java Solutions


Solution 1 - Java

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

Solution 2 - Java

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

Solution 3 - Java

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)

Solution 4 - Java

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.

Solution 5 - Java

Java 8 solution using Map#merge

As of [tag:java-8] 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 >

Solution 6 - Java

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

Solution 7 - Java

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.

Solution 8 - Java

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionrapaduraView Question on Stackoverflow
Solution 1 - JavaericksonView Answer on Stackoverflow
Solution 2 - JavaTom TresanskyView Answer on Stackoverflow
Solution 3 - JavaReverend GonzoView Answer on Stackoverflow
Solution 4 - JavaAnatolii StepaniukView Answer on Stackoverflow
Solution 5 - JavaNikolas CharalambidisView Answer on Stackoverflow
Solution 6 - JavaJajikanth pydimarlaView Answer on Stackoverflow
Solution 7 - JavanewdayView Answer on Stackoverflow
Solution 8 - Javawhistling_marmotView Answer on Stackoverflow