-
Enhancement
-
Resolution: Won't Fix
-
P4
-
None
-
6
-
generic
-
generic
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)));
}
}
}
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)));
}
}
}
- relates to
-
JDK-6270657 (coll) remove/contains and "Equators" other than .equals()
- Open
-
JDK-4771660 (coll) Comparator, Comparable, Identity, and Equivalence
- Open
-
JDK-4269596 (coll) Wanted: A way to customize the equals/hashCode algorithm
- Closed