简体   繁体   中英

Java combining two hashmaps of the same type into a new hashmap keeping duplicates

Assume we are given:

Map<String, String> map1 = new HashMap<>();
map1.put("111","Frank");
map1.put("222","Ted");
map1.put("555","Peter");

Map<String, String> map2 = new HashMap<>();
map2.put("333","Roger");
map2.put("222","Ted");
map2.put("888","Kent");
map2.put("555","Peter");

How could I go about combining both of these into a new map:

Map<String, String> combinedMap = new HashMap<>();

I wanted to do it in a java stream way, so my attempt was:

combinedMap = Stream.of(map1, map2)
                        .flatMap(m -> m.entrySet().stream())
                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

But I was hit with some duplicate key error. I believe I could also just do a combinedMap.putAll(map1) and combinedMap.putAll(map2) but I'm not sure if that's the best way possible.

You almost had it with your use of a Java stream. The only thing you missed that you can provide a "merger function" that takes care of resolving collisions when the same key exists in both maps. Since it doesn't matter in our case which one we pick, I added a very simple merger that just pick one of them arbitrarily:

combinedMap = Stream.of(map1, map2)
    .flatMap(m -> m.entrySet().stream())
    .collect(Collectors.toMap(
        Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1));

System.out.println(combinedMap);

Results:

{111=Frank, 222=Ted, 333=Roger, 555=Peter, 888=Kent}

If you want to keep duplicates, then Map is not the correct data-structure. You need something like a MultiMap or Map<String,List<String>> .

An Example:

public class Main {

    public static void main(String[] args) {
        System.out.println(combine(Map.of("111", "sam"), Map.of("222", "joe", "111","tim")));
    }

    public static Map<String, List<String>> combine(Map<String, String>... maps) {
        return Arrays.stream(maps).flatMap(m -> m.entrySet().stream())
                .collect(Collectors.toMap(e -> e.getKey(), e -> Arrays.asList(e.getValue()), (v1, v2) -> Stream.of(v1, v2).flatMap(List::stream).collect(Collectors.toList())));
    }
}

If your final HashMap can have multiple entries for a single key, then you must store these entries in some sort of a sequence. There is simply no other way around it.

As suggested by other users, the previous entry with the same key will be replaced with the new entry if the entry is not a sequence.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM