ConcurrentHashMap
and HashMap
are using equals()
/hashCode()
of the key instances.
Over the decades, on quite a few occasions, I have missed the possibility to provide different equals/hashCode implementations. Not being able to do this means you either have to use a sorted map, which allows you to set a Comparator
, at the cost of SortedMap's worse performance characteristics, or you have to use different objects as your keys, i.e. by creating key wrapper instances that provide their own equals/hashCode implementations.
In the latter case, the need to create another object for every key has obvious memory and performance implications. (In the current case I'm looking at, it would mean the creation of hundreds of thousands of additional object instances per second at peak times - which is where performance matters most.)
This seems like such a trivial and safe change to do, with huge performance benefits in the cases where it is needed.
.Net has been offering this for its Dictionary
since at least version 1.1. So are there any good, technical reasons why Java does not?
This was requested as an RFE for Java 1.2.2 and so on, but never implemented and eventually closed. https://bugs.openjdk.org/browse/JDK-4269596
Joshua Bloch's analysis in 1999 was:
When the Collections Framework was designed, we thought hard about whether to include support for custom equals/hashCode methods. In the end, we rejected it on the grounds of increased complexity, and inconsistency with other design decisions. In particular, the decision that List, Set and Map objects can be compared independent of their representation is inconsistent with support for custom equals methods.
Moreover, full support for custom equals methods is probably overkill. 99% of the time, when a developer wants a collection with a custom equals method, the desired equals method is element identity. This suggests an alternate solution, which is to provide one or two special-purpose implementations that are based on identity rather than equality. Of course these implementations would not be "good citizens of the realm", in that they could not be properly compared to other collections. (Which equals method would you use?) This is not without precedent, however. It is possible to make a SortedMap/Set that violates the Map/Set contract, by specifiying a Comparator that is not "consistent with equals."
I am leaving this RFE open to track support for special-purpose, identity-based Set and Map implementations.
The final comment (in 2011) notes that identity-based use-cases have been addressed via IdentityHashMap
etc.
There a number of linked issues if you want to trawl through them.
Having said that, if you want a Java hash table implementation that allows you use a different hashCode
and equals
to those implemented by the key type, there are 3rd party libraries that support this. For example, Apache Commons Collections AbstractHashedMap
(javadoc). There are other possibilities listed in this Q&A: Custom hashcode/equals operation for HashMap.