117. Merging two maps

Merging two maps is the process of joining two maps into a single map that contains the elements of both maps. Furthermore, for key collisions, we incorporate in the final map the value belonging to the second map. But this is a design decision.

Let's consider the following two maps (we intentionally added a collision for key 3):

public class Melon {

private final String type;
private final int weight;

// constructor, getters, equals(), hashCode(),
// toString() omitted for brevity
}

Map<Integer, Melon> melons1 = new HashMap<>();
Map<Integer, Melon> melons2 = new HashMap<>();
melons1.put(1, new Melon("Apollo", 3000));
melons1.put(2, new Melon("Jade Dew", 3500));
melons1.put(3, new Melon("Cantaloupe", 1500));
melons2.put(3, new Melon("Apollo", 3000));
melons2.put(4, new Melon("Jade Dew", 3500));
melons2.put(5, new Melon("Cantaloupe", 1500));

Starting with JDK 8, we have the following method in Map: V merge​(K key, V value, BiFunction<? super V,​? super V,​? extends V> remappingFunction).

If the given key (K) is not associated with a value, or is associated with null, then the new value will be V. If the given key (K) is associated with a non-null value, then the new value is computed based on the given BiFunction. If the result of this BiFunction is null, and the key is present in the map, then this entry will be removed from the map.

Based on this definition, we can write a helper method for merging two maps as follows:

public static <K, V> Map<K, V> mergeMaps(
Map<K, V> map1, Map<K, V> map2) {

Map<K, V> map = new HashMap<>(map1);

map2.forEach(
(key, value) -> map.merge(key, value, (v1, v2) -> v2));

return map;
}

Note that we don't modify the original maps. We prefer to return a new map containing the elements of the first map merged with the elements of the second map. In the case of a collision of keys, we replace the existing value with the value from the second map (v2).

Another solution can be written based on Stream.concat(). Basically, this method concatenates two streams into a single Stream. In order to create a Stream from a Map, we call Map.entrySet().stream(). After concatenating the two streams created from the given maps, we simply collect the result via the toMap() collector:

public static <K, V> Map<K, V> mergeMaps(
Map<K, V> map1, Map<K, V> map2) {

Stream<Map.Entry<K, V>> combined
= Stream.concat(map1.entrySet().stream(),
map2.entrySet().stream());

Map<K, V> map = combined.collect(
Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(v1, v2) -> v2));

return map;
}

As a bonus, a Set (for example, a Set of integers) can be sorted as follows:

List<Integer> sortedList = someSetOfIntegers.stream()
.sorted().collect(Collectors.toList());

For objects, rely on sorted(Comparator<? super T>.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.27.72