Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merge two maps with Java 8

I have two maps like this:

map1 = new Map<String, MyObject>();
map2 = new Map<String, MyObject>();

MyObject {
   Integer mark1;
   Integer mark2;
}

What I want to do to is to merge the two maps into a map3 <String, MyObject> like this:

  1. If map1.place is not in map2.place, then I add the entry to map3.
  2. same if map2.place is not in map1.place, I add the entry to map3.
  3. if map1.place is in map2.place, then I add this entry:
  • map1.place, (map1.mark1, map2.mark2)

I have read about flatMap, but I really have a hard time using it. Any clue how to do this?

like image 801
dardy Avatar asked Oct 20 '16 15:10

dardy


People also ask

How do I merge two maps together?

Alternatively, we can use Stream#concat() function to merge the maps together. This function can combine two different streams into one. As shown in the snippet, we are passed the streams of map1 and map2 to the concate() function and then collected the stream of their combined entry elements.

How do you concatenate a map in Java?

You can combine two maps in Java by using the putAll() method of java. util. Map interface. This method copies all the mappings from one Map to another, like, if you call it like first.

Can you combine two maps in Minecraft?

You can't merge maps. The only way to fully explore a map is to manually explore all the terrain shown on the map while holding that map.


2 Answers

It can be done using the Stream API with the appropriate mergeFunction as next:

Map<String, MyObject> map3 = Stream.of(map1, map2)
    .flatMap(map -> map.entrySet().stream())
    .collect(
        Collectors.toMap(
            Map.Entry::getKey,
            Map.Entry::getValue,
            (v1, v2) -> new MyObject(v1.getMark1(), v2.getMark2())
        )
    );

This concatenates entries of map1 followed by the entries of map2, then convert everything as a Map with a merge function that will use mark1 from the first value (the one from map1) and mark2 from the second value (the one from map2) in case of duplicate keys.


Or it could also be done using a different Supplier<Map> that will propose a map that already contains the entries of map1 then we can focus only on adding the entries of map2 as next:

Map<String, MyObject> map3 = map2.entrySet()
    .stream()
    .collect(
        Collectors.toMap(
            Map.Entry::getKey,
            Map.Entry::getValue,
            (v1, v2) -> new MyObject(v1.getMark1(), v2.getMark2()),
            () -> new HashMap<>(map1)
        )
    );
like image 141
Nicolas Filotto Avatar answered Oct 15 '22 08:10

Nicolas Filotto


Here is what I think would work

Map<String, MyObj> map3 = new HashMap<>(map1);
map2.forEach(
    (key, value) -> map3.merge(key, value, (v1, v2) -> new MyObject(v1.mark1,v2.mark2))
);

The merge function is what is taking care of your scenario 3, in that if the key already exists, it creates a new MyObject with v1.mark1 and v2.mark2

like image 33
Ash Avatar answered Oct 15 '22 07:10

Ash