equals and hashCode

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.
 
T

Tom Dyess

Lol. Thanks for noticing, Vergil.
Crap, I spelled that wrong as well, Virgil. Is it tomorrow yet?
 
C

Chris Uppal

Andrew said:
Always, start with creating the equals method, then make the hashCode
work.

Agreed, but create an empty hashCode() method when you create the equals()
method, or you're likely to forget...

BTW, when you do get round to setting up the hash code remember that you don't
have to include every little detail that you'll be comparing in the equals()
method. If (this is a slightly strained example, I admit) you had a person
with account number, first name, and last name, then it would probably be a
waste of time to include the two names in the hash even if the same account
number were allowed to be used by more than one person.

-- chris
 
T

Tom Dyess

Agreed, but create an empty hashCode() method when you create the equals()
method, or you're likely to forget...

Yes, I employ this technique for languages that require manual freeing of
objects as well as opening/closing recordsets. Works every time and sure
beats searching the code looking for memory leaks cause by constructed
objects that weren't freed.
 
A

Andrew McDonagh

Chris said:
Andrew McDonagh wrote:




Agreed, but create an empty hashCode() method when you create the equals()
method, or you're likely to forget...

Agreed, I've had a todo on my list to change Eclipse's code generator to
do just that when overriding equals().
BTW, when you do get round to setting up the hash code remember that you don't
have to include every little detail that you'll be comparing in the equals()
method. If (this is a slightly strained example, I admit) you had a person
with account number, first name, and last name, then it would probably be a
waste of time to include the two names in the hash even if the same account
number were allowed to be used by more than one person.

-- chris

Also good advice for the op - its easy for us to forget these little
snippets eh ;-)
 
B

Boudewijn Dijkstra

Patricia Shanahan said:
Boudewijn Dijkstra wrote:
...
...

Shouldn't that be 2^32, the number of distinct values of an int? A hash
code does not have to be positive.

My mistake. Damn those pesky signed numers!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,144
Latest member
KetoBaseReviews
Top