Merging combine and composing Maps and Add multiple items


Merging, combine and composing Maps

Use putAll to put every member of one map into another. Keys already present in the map will have their corresponding values overwritten.

Map<String, Integer> numbers = new HashMap<>();
numbers.put("One", 1)
numbers.put("Three", 3)
Map<String, Integer> other_numbers = new HashMap<>();
other_numbers.put("Two", 2)
other_numbers.put("Three", 4)
numbers.putAll(other_numbers)

This yields the following mapping in numbers:

"One" -> 1
"Two" -> 2
"Three" -> 4 //old value 3 was overwritten by new value 4

If you want to combine values instead of overwriting them, you can use Map.merge, added in Java 8, which uses a user-provided BiFunction to merge values for duplicate keys. merge operates on individual keys and values, so you'll need to use a loop or Map.forEach. Here we concatenate strings for duplicate keys:

for (Map.Entry<String, Integer> e : other_numbers.entrySet())
numbers.merge(e.getKey(), e.getValue(), Integer::sum);
//or instead of the above loop
other_numbers.forEach((k, v) -> numbers.merge(k, v, Integer::sum));

If you want to enforce the constraint there are no duplicate keys, you can use a merge function that throws an AssertionError:

mapA.forEach((k, v) ->
     mapB.merge(k, v, (v1, v2) ->
         {throw new AssertionError("duplicate values for key: "+k);}));

Composing Map<X,Y> and Map<Y,Z> to get Map<X,Z>

If you want to compose two mappings, you can do it as follows

Map<String, Integer> map1 = new HashMap<String, Integer>();
map1.put("key1", 1);
map1.put("key2", 2);
map1.put("key3", 3);
 
Map<Integer, Double> map2 = new HashMap<Integer, Double>();
map2.put(1, 1.0);
map2.put(2, 2.0);
map2.put(3, 3.0);
 
Map<String, Double> map3 = new new HashMap<String, Double>();
map1.forEach((key,value)->map3.put(key,map2.get(value)));

This yields the following mapping

"key1" -> 1.0
"key2" -> 2.0
"key3" -> 3.0

Add multiple items

We can use V put(K key,V value):

  • Associates the specified value with the specified key in this map (optional operation). If the map previously contained a mapping for the key, the old value is replaced by the specified value.
String currentVal;
Map<Integer, String> map = new TreeMap<>();
currentVal = map.put(1, "First element.");
System.out.println(currentVal);// Will print null
currentVal = map.put(2, "Second element.");
System.out.println(currentVal); // Will print null yet again 
currentVal = map.put(2, "This will replace 'Second element'");
System.out.println(currentVal); // will print Second element.
System.out.println(map.size()); // Will print 2 as key having
// value 2 was replaced.
 
Map<Integer, String> map2 = new HashMap<>();
map2.put(2, "Element 2");
map2.put(3, "Element 3");
 
map.putAll(map2);
 
System.out.println(map.size());

Output:

3

To add many items you can use an inner classes like this:

Map<Integer, String> map = new HashMap<>() {{
 // This is now an anonymous inner class with an unnamed instance constructor
 put(5, "high");
 put(4, "low");
 put(1, "too slow");
}};

Keep in mind that creating an anonymous inner class is not always efficient and can lead to memory leaks so when possible, use an initializer block instead:

static Map<Integer, String> map = new HashMap<>();
static {
 // Now no inner classes are created so we can avoid memory leaks
 put(5, "high");
 put(4, "low");
 put(1, "too slow");
}

The example above makes the map static. It can also be used in a non-static context by removing all occurrences of static.

In addition to that most implementations support putAll, which can add all entries in one map to another like this:

another.putAll(one);

Basic Programs