2

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?

Eran
395k57 gold badges725 silver badges792 bronze badges
asked May 6, 2018 at 12:59
1
  • You are using a convoluted way to do m1.putAll(m2) or, if you need a new map, finalMap = new LinkedHashMap<>(m1); finalMap.putAll(m2)... Commented May 7, 2018 at 7:26

1 Answer 1

2

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}
answered May 6, 2018 at 13:03
1
  • Brilliant mate...I was so close to figuring this out..only if I looked at the API in one more line. Thank you. Commented May 6, 2018 at 13:31

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.