Re: Java HashSet Problem
Let's digg up this thread because to me it seems the JavaDoc on
HashSet#contains(Object o) is not right.
It all started with these lines in a unit-test (and a failure on the
last line):
Person bob = new Person("Bob", 'm', new Date(1, 7, 2007), "1");
Set<Person> store = new HashSet<Person>();
store.add(bob);
assertTrue(bob.equals(new Person( //
"Bob", 'm', new Date(1, 7, 2007), "1")));
assertTrue(store.contains(bob));
assertTrue(store.contains(new Person( //
"Bob", 'm', new Date(1, 7, 2007), "1")));
Person overwrites equals(Object) in a correct way, but does not
overwrite the hashCode() method.
When I look at the JavaDoc of HashSet#contains(Object o) I get:
"
Returns true if this set contains the specified element. More
formally,
returns true if and only if this set contains an element e such
that
(o==null ? e==null : o.equals(e)).
"
But! when we check the source of the HashSet#contains(Object
ourPerson) we see it uses HashMap.containsKey(Object ourPerson) which
uses HashMap.getEntry(Object ourPerson). now getEntry's source looks
like:
"
int hash = (key == null) ? 0 : hash(key.hashCode());
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
}
return null;
"
If I am reading this correctly, then the equals method is only
evaluated when the hashes of the two objects are equals. Since I did
not overwrite Object#hashCode() HashSet#contains(Object) returns false
in the above scenario.
Since I couldn't find any other post on this matter (or bug-report) I
want to ask you guys to check my above statements.
Ow, for the record the HashSet class I have is labeled:
/*
* @(#)HashSet.java 1.37 06/04/21
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
and my java lives In C:\jdk1.6.0_03 (so that would probably be the
version then)
Cheers,
Paul