JDK-4269596 : (coll) Wanted: A way to customize the equals/hashCode algorithm
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.util:collections
  • Affected Version: 1.2.2,1.3.0,1.4.0,5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: generic,linux,windows_xp
  • CPU: generic,x86
  • Submitted: 1999-09-07
  • Updated: 2012-10-08
  • Resolved: 2011-04-05
Related Reports
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
Name: skT88420			Date: 09/07/99


The Java 2 SDK includes the classes HashMap, HashSet and Hashtable
in the java.util package. These classes are all implemented based
on the usual meaning of Object.equals and Object.hashCode. 

However, suppose I want to create a HashMap (or HashSet, or Hashtable) where
the usual rules don't apply. For example, I want to create a
HashMap where two keys are identical if and only if they are the
exact same object, regardless of the result of Object.equals. To
accomplish this, I must re-implement nearly all of HashMap just
to make this one little change. My life would be much simpler if
there were a couple simple functions which I could override to
re-define HashMap's concept of a hashCode.

If HashMap, HashSet and Hashtable used the following methods,
instead of calling hashCode and equals directly on the key, then
it would be possible to override them if necessary to customize
their behavior.


protected int hashCode(Object o) {
    return (o != null) ? o.hashCode() : 0;
}

protected boolean equals(Object a, Object b) {
    return (a == b) || ((a != null) && a.equals(b));
}


For example, I could implement the behavior I described earlier
by simply extending the HashMap class and overriding the above
methods as...


protected int hashCode(Object o) {
    return System.identityHashCode(o);
}

protected boolean equals(Object a, Object b) {
    return (a == b);
}
(Review ID: 94977) 
======================================================================


We could create a Hasher interface for the suggested methods.

public interface Hasher
{
    public int hashCode(Object hashMe);
    public boolean equals(Object a, Object b);
}


These methods are helpful for creating a case-insensitive HashMap.

###@###.###

======================================================================

Comments
EVALUATION IdentityHashMap added in 1.4 collections. Collections.newSetFromMap added in 1.6 satisfies IdentityHashSet requirement.
05-04-2011

WORK AROUND Name: skT88420 Date: 09/07/99 The workaround is to re-implement the Hashtable class. Its not a terribly difficult task, but it seems like more work than should be required. ======================================================================
08-09-2004

EVALUATION 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. joshua.bloch@Eng 1999-09-08
08-09-1999