Issue
I have created a map with maps inside as a test and it seems that the outer map will ignore the rest of the maps. I assume it is overriding them. Also I presume that it is because they all extend from Map so it is treating them as the same instance when they are not.
Map<Map<Integer, String>,String> maps=new HashMap<>();
maps.put(new HashMap<Integer, String>(),"HashMap");
maps.put(new TreeMap<Integer, String>(),"TreeMap");
maps.put(new LinkedHashMap<Integer, String>(),"LinkedHashMap");
maps.put(new Hashtable<Integer, String>(),"Hashtable");
Printing the map to logs will show only the last one added:
maps: {{}=Hashtable}
I tried with other Map implementations and all have the same behavior except TreeMap which will throw an exception due to the fact that HashMap does not implement Comparable.
Is this expected behavior? Why does HashMap behave like this?
Solution
When we take a look at the documentation of Map::equals, we see that this method
Returns
trueif the given object is also a map and the two maps represent the same mappings. More formally, two mapsm1andm2represent the same mappings ifm1.entrySet().equals(m2.entrySet()).
Due to the contract between Object::equals and Object::hashCode, this means that those maps will also have the same hash code. This, in return, means that they are, for Map::put, indistinguishable. Thus, each put(...) in the sample program overrides the previous put and thus results in a final map size of 1 with only the HashTable in the entrySet().
So yes, this is expected behaviour. And it is not only expected for HashMap, but for all Map implementations.
As was already pointed out in the comments by Pshemo, it is questionable to use a Map as key for another Map and, in general, we should use immutable objects as keys.
Answered By - Turing85
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.