Mark Estrada
Mark Estrada

Reputation: 9191

ClasscastException Merging Two LinkedHashMap

I am trying to merge two LinkedHashMap.. My rule is that if there are duplicates in the key for both maps.. then the values of the 2nd Map should prevail and override the 1st map.

Here is my code:

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamMerge {
    public static void main(String[] args) {
        LinkedHashMap<String, Object> m1 = new LinkedHashMap<String, Object>();
        m1.put("A", "1");
        m1.put("B", "2");
        m1.put("C", "3");
        LinkedHashMap<String, Object> embeddedMap =  new LinkedHashMap<String, Object>();
        embeddedMap.put("D", "10");
        embeddedMap.put("E", "20");
        m1.put("embed", embeddedMap);


        LinkedHashMap<String, Object> m2 = new LinkedHashMap<String, Object>();
        m2.put("A", "1");
        m2.put("B", "2");
        m2.put("C", "4");
        LinkedHashMap<String, Object> embeddedMap2 =  new LinkedHashMap<String, Object>();
        embeddedMap2.put("D", "10");
        embeddedMap2.put("E", "20");
        m2.put("embed", embeddedMap2);
        m2.put("F", "100");

        LinkedHashMap<String, Object> finalMap = (LinkedHashMap<String, Object>)Stream.concat(m1.entrySet().stream(), m2.entrySet().stream())
            .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue(), (map1, map2) -> {
                System.out.println("m1" + m1.getClass());
                System.out.println("m2" + m2.getClass());
                return map2;
            }));
        System.out.println(finalMap);
    }
}

My problem, is that when I try to run this.. I am getting this exception.

Exception in thread "main" java.lang.ClassCastException: java.util.HashMap cannot be cast to java.util.LinkedHashMap
    at com.oracle.lambda.StreamMerge.main(StreamMerge.java:36)
m1class java.util.LinkedHashMap
m2class java.util.LinkedHashMap
m1class java.util.LinkedHashMap
m2class java.util.LinkedHashMap
m1class java.util.LinkedHashMap
m2class java.util.LinkedHashMap
m1class java.util.LinkedHashMap
m2class java.util.LinkedHashMap

The workaround that I am doing is to cast it to a HashMap

HashMap<String, Object> finalMap = (HashMap<String, Object>)Stream.concat(m1.entrySet().stream(), m2.entrySet().stream())
    .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue(), (map1, map2) -> {
        System.out.println("m1" + m1.getClass());
        System.out.println("m2" + m2.getClass());
        return map2;
    }));
System.out.println(finalMap);

But the order gets messed up since it is now a HashMap.. 'F" should be at the end.

{A=1, B=2, C=4, F=100, embed={D=10, E=20}}

Is there something wrong in my code?

Upvotes: 2

Views: 398

Answers (1)

Eran
Eran

Reputation: 393801

Collectors.toMap() is not required to return any specific implementation of the Map interface. It currently returns a HashMap, but that's just an implementation detail.

You can force it to return a LinkedHashMap by calling a different variant:

LinkedHashMap<String, Object> finalMap = 
    Stream.concat(m1.entrySet().stream(), m2.entrySet().stream())
          .collect(Collectors.toMap(entry -> entry.getKey(),
                                    entry -> entry.getValue(),
                                    (v1, v2) -> v2,
                                    LinkedHashMap::new));

The output Map would be printed as:

{A=1, B=2, C=4, embed={D=10, E=20}, F=100}

Upvotes: 2

Related Questions