merge two Map Values in Java and if key is same append the Values not overwrite in Java 7 or Java 8

8.3k Views Asked by At

I want to merge 2 Maps, but when the key is the same, the values should be appended instead of overwritten.

Let's say

Map<String, Set<String>> map1 = new HashMap<>();
Set<String> set1 = new HashSet<>();
set1.add("AB");
set1.add("BC");
map1.put("ABCD",set1);

Map<String, Set<String>> map2 = new HashMap<>();
Set<String> set2 =new HashSet<>();
set2.add("CD");
set2.add("EF");
map2.put("ABCD",set2);

map1.putAll(map2);

So here the key is same.I know putAll will overwrite the values if key is same

But I am looking for an output like

{ABCD=[AB,BC,CD,ED]}

If someone can help me to resolve, will be so thankful.

3

There are 3 best solutions below

0
On BEST ANSWER

You make use of the merging function provided to Collectors.toMap that specifies what to do with values of duplicate keys with Streams. Demo

final Map<String, Set<String>> map3 = Stream.concat(map1.entrySet().stream(), map2.entrySet().stream())
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                (a, b) -> Stream.concat(a.stream(), b.stream()).collect(Collectors.toSet())));

You can apply a similar approach using Map#merge. Demo

final Map<String, Set<String>> map3 = new HashMap<>(map1);
map2.forEach((key, val) -> map3.merge(key, val,
        (a, b) -> Stream.concat(a.stream(), b.stream()).collect(Collectors.toSet())));
1
On

You can use Stream API to merge the values of the same keys, Check if the map2 has the same keys from map1 and loop over them and merge the values together using addAll()

map1.entrySet().stream().filter(entry -> map2.containsKey(entry.getKey()))
                .forEach(entry -> entry.getValue().addAll(map2.get(entry.getKey())));

, main function

public static void main(String[] args) {
    Map<String, Set<String>> map1 = new HashMap<>();
    Set<String> set1 = new HashSet<>();
    set1.add("AB");
    set1.add("BC");
    map1.put("ABCD", set1);

    Map<String, Set<String>> map2 = new HashMap<>();
    Set<String> set2 = new HashSet<>();
    set2.add("CD");
    set2.add("EF");
    map2.put("ABCD", set2);

    map1.entrySet()
        .stream()
        .filter(entry -> map2.containsKey(entry.getKey()))
        .forEach(entry -> entry.getValue().addAll(map2.get(entry.getKey())));

    System.out.println(map1);
}

, output

{ABCD=[AB, BC, CD, EF]}
3
On

You can concat two maps using Stream.concat then collect using groupingBy map key and value as Set.

Map<String, Set<String>> res = 
       Stream.concat(map1.entrySet().stream(), map2.entrySet().stream())
             .collect(Collectors.groupingBy(e-> e.getKey(),
                                Collectors.flatMapping(e -> e.getValue().stream(), Collectors.toSet())));

Note: Solution use Java 9+ flatMapping

Or

You can use merge function of map. Here merge map2 data into map1

map2.forEach((key, val) -> map1.merge(key, val, (a, b) -> {a.addAll(b); return a;}));

Output: {ABCD=[AB, BC, CD, EF]}