A
Andrew McDonagh
Tom said:This is gonna be a tough question to put into words, but here goes:
I understand the purpose of overriding equals() in comparing the data of an
object verses the reference, but the requirement to override hashCode() is a
little less clear.
Consider this idiom from this reference:
http://www.geocities.com/technofundo/tech/java/equalhash.html
"Equal objects must produce the same hash code as long as they are equal,
however unequal objects need not produce distinct hash codes."
As far as the contract for hashCode() goes, the value it returns does
not have to be unique. In fact we can not and must not rely upon the
hashCode being unique. hashCode is not an identifier of the object
Its worth knowing that its common for two instances of unrelated classes
to produce the same hashCode value.
The purpose of hashCode is for hashing efficiency used by HashSet,
HashTable, HashMap, etc.
In general, the hashCode is used to determine which bucket the object is
placed in, so that fast retrival can occur because we don't have to
compare every element within the collection, just every element within
the bucket.
here's the HashMap.containsKey() method showing the retrival and
comparisons of each entry with the bucket.
*/
public boolean containsKey(Object key) {
Object k = maskNull(key);
int hash = hash(k);
int i = indexFor(hash, table.length);
Entry e = table;
while (e != null) {
if (e.hash == hash && eq(k, e.key))
return true;
e = e.next;
}
return false;
}
The advice wrt to overriding equals() is that you should also override
hashCode() to ensure the efficiencies of the hashing algorithms.
The simplest way to create an equals and hashCode implementation for an
object would be to make a distinct hash code based on the value of the data
in the object, then in equals(), simply compare the value of hash codes. Why
would I not want to make a distinct hashCode based on the data - i.e.
"however unequal objects need not produce distinct hash codes"
Thanks for any information. I'm researching this because we are using
Hibernate in our project and want to understand how it can apply.
This might work, but is not a good general practise, consider...
Class Person {
private String forename;
private String surname;
public Person(String theirName, String theirSurname) {
name = theirName;
surname = theirSurname;
}
public int hashCode() {
return foreName.hashCode() + surname.hashCode();
}
public boolean equals(Object o) {
Person other = (Person) o;
return other.hashCode() = this.hashCode();
}
}
if the created two instances with different values, but reversed..
Person p1 = new Person("Andrew", "John");
Person p2 = new Person("John", "Andrew");
its possible that the hashCode value for both objects would be the same
and so if we used the hashCode as an equality comparitor, a false
positive would result.
Always, start with creating the equals method, then make the hashCode work.