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:
The final comment (in 2011) notes that identity-based use-cases have been addressed via
IdentityHashMapetc.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
hashCodeandequalsto those implemented by the key type, there are 3rd party libraries that support this. For example, Apache Commons CollectionsAbstractHashedMap(javadoc). There are other possibilities listed in this Q&A: Custom hashcode/equals operation for HashMap.