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
true
if the given object is also a map and the two maps represent the same mappings. More formally, two mapsm1
andm2
represent 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.