JDK-6435963 : (coll) Hasher interface to be used by a HashMap/HashSet
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.util:collections
  • Affected Version: 6
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: generic
  • CPU: generic
  • Submitted: 2006-06-08
  • Updated: 2012-10-08
  • Resolved: 2010-12-28
Related Reports
Relates :  
Relates :  
Relates :  
Description
A DESCRIPTION OF THE FIX :
The actual code changes are smallish, but could affect a variety of classes.  Mainly (initially), HashMap and HashSet would be affected.  The changes would be to integrate the following interfaces, where the Hasher interface would be used by a HashMap/HashSet in the same way that a Comparator is used by a TreeMap/TreeSet.

public interface Equater<T> {
  public boolean equals(T o1, Object o2);
}

public interface Hasher<T> extends Equater<T> {
  public int hashCode(T o);
} 

I have made the Equater interface separate, however, because it could be utilized in some of the other collections.  For instance, a very useful convenience method in the Collections class could be (could also do remote()):

public static <T> boolean contains(Collection<T> col, Object o, Equater<? super T> eq) {
  for(T t : col) {
    if(eq(t, o)) return true;
  }
  return false;
}

I have posted about this in the forums, which can be found here:
http://forums.java.net/jive/thread.jspa?threadID=14743

JUnit TESTCASE :
public class HasherTest extends TestCase {
  public HasherTest(String name) { super(name); }

  public void testHasher() throws Exception {
  
    TestClass t1 = new TestClass(13, 24);
    TestClass t2 = new TestClass(14, 25);
    TestClass t3 = new TestClass(15, 24);

    Set<TestClass> testSet = new HashSet<TestClass>();
    testSet.addAll(Arrays.asList(t1, t2, t3));
    assertEquals(3, testSet.size());
    assertTrue(testSet.contains(t1));
    assertTrue(testSet.contains(t2));
    assertTrue(testSet.contains(t3));

    Set<TestClass> testSet = new HashSet<TestClass>(new Hasher<TestClass>() {
      public boolean equals(TestClass o1, Object o2) {
        return((o1 == o2) || ((o1 != null) && (o2 != null) && (o1.getClass() == o2.getClass()) && (o1.value2 == ((TestClass)o).value2)));
      }
      public int hashCode(TestClass o) {
        return o.value2;
      }
      });
    testSet.addAll(Arrays.asList(t1, t2, t3));
    assertEquals(2, testSet.size());
    assertTrue(testSet.contains(t1));
    assertTrue(testSet.contains(t2));
    assertTrue(testSet.contains(t3));
  }

  private static class TestClass {
    public int value1;
    public int value2;
    
    public TestClass(int v1, int v2) {
      this.value1 = v1;
      this.value2 = v2;
    }
    
    @Override
    public int hashCode() { return this.value1; }
  
    @Override
    public boolean equals(Object o) {
      return((this == o) || ((o != null) && (getClass() == o.getClass()) && (this.value1 == ((TestClass)o).value1)));
    }
  }
}

Comments
PUBLIC COMMENTS No changes planned in this area currently. Please pursue this idea with JSR 166 group if it remains relevent.
28-12-2010

EVALUATION There is a group of related suggestions. Doug Lea/Josh Bloch might be working on improvements.
08-06-2006