Summary
The implementation of HashMap.get is stricter than the specification of HashMap.get. The disparity can obscure inconsistent behavior in the .equals method of key classes. Other HashMap methods use similarly imprecise implementations, for example `remove'().
Problem
The implementation of HashMap.get(key) is specified to compare keys with an entry as:
key == null ? entry.key == null : key.equals(entry.key)
The implementation adds a reference equality comparison as a shortcut:
key == entry.key || (key != null && key.equals(entry.key)))
The contract for Object.equals methods is that an object is equal to itself. The assumption and expectation is that the shortcut and the result of calling .equals are identical.
In the case of an object used as a key does not satisfy its contract can result in unexpected behavior of HashMap. Failing to find an existing entry or failing to remove an entry. Correct semantics of HashMap depend on the correct implementation of the key class .equals .
Typically, most implementations of .equals explicitly check for reference equality and do not have this deficiency.
The current implementation of HashMap compensates for inconsistent/incorrect implementation of the key classes. Specifically, ensuring that a key instance is equal to itself.
Solution
The change proposed is to remove the check for reference equality and no longer compensate for a possibly incorrect .equals implementation. The impact of this change is to expose the deficiency in .equals methods in classes used as keys and indexes. Most frequently with HashMap and ConcurrentHashMap. These deficiencies are usually found during development but may go undetected into production.
An example of deficient .equals methods exists in the BCEL InstructionComparator used in xml transform implementation. The particular implementation can be fixed with a local change to InstructionComparator.equals. The scale of the classes used as keys is hard to estimate but is significant.
Specification
There is no change to the specification, the implementation is relaxed to match the specification.
- csr of
-
JDK-8373361 Use of identity in HashMap and ConcurrentHashmap comparisons
-
- Open
-