Re: hashCode() for Custom classes
sasuke wrote:
Wow, thanks a lot for such overwhelming replies to this thread, I
never thought this amount of thinking went into devising a hashCOde()
function for custom classes. I really appreciate the time and effort
everyone has put into replying to this thread.
A few points I would like to put from my side.
I never thought of the possibility of XORing the values instead of
doing plain jane addition. I will keep in mind to always use XOR
instead of addition given the benefits of uniform distribution offered
by it though I am not sure how this can be proved mathematically.
(considering I am pretty bad at math)
Keep in mind that both addition and XOR are commutative,
meaning that exchanging the order of the operands produces
no change in the result. In some classes this could be a
drawback, for instance
class Position {
private int x;
private int y;
...
public int hashCode() {
return x + y; // or x ^ y
}
}
The points (x=2,y=3) and (x=3,y=2) have the same hashCode().
More generally, consider the points at the corners of any
rectangle whose sides are parallel to the axes: the four points
will generate at most two different hashCodes(), practically
guaranteeing a higher-than-normal collision rate.
Not all classes are vulnerable to this sort of thing; for
example in
class Employee {
private String name;
private int id_number;
...
public int hashCode() {
return name.hashCode() + id_number;
}
}
.... it probably wouldn't worry you that ("Adam Smith",16123)
and (16123,"Adam Smith") have the same hash. But it's usually
good to avoid collisions from simple rearrangements.
As far as caching the hashCode computed, this can't be done since my
class is not immutable so I would end up tracking changes to my member
variables and re-calculating the hashCode() everytime a variable is
modified i.e. everytime a setter is called.
It's seldom a good idea for an object's hashCode() to change
during the object's lifetime. Suppose you use such an object as
a key in a HashMap. When you insert the key,value pair, HashMap
calls the key's hashCode() method and gets a value we'll call H1.
Then you change the object and try to look it up in the Map. The
HashMap calls hashCode() again and gets a value H2 that is very
probably different from H1. So the HashMap looks in the bucket
where H2 values land, and unless you happen to be very lucky this
will be a different bucket from where the H1's go. The HashMap
thus probably doesn't find the key object (even though it's there)
and the key has lost its usefulness. Similar remarks apply to
other hash-based data structures.
If you're planning to calculate hashes on mutable objects,
you should probably re-think your plan very carefully before
proceeding.
--
Eric.Sosman@sun.com