Let’s say I have the following class:
class ABC {
private int myInt = 1;
private double myDouble = 2;
private String myString = "123";
private SomeRandomClass1 myRandomClass1 = new ...
private SomeRandomClass2 myRandomClass2 = new ...
//pseudo code
public int myHashCode() {
return 37 *
myInt.hashcode() *
myDouble.hashCode() *
... *
myRandomClass.hashcode()
}
}
Would this be a correct implementation of hashCode? This is not how I usually do it(I tend to follow Effective Java’s guide-lines) but I always have the temptation to just do something like the above code.
Thanks
It depends what you mean by “correct”. Assuming that you’re using the
hashCode()of all the relevantequals()-defining fields, then yes, it’s “correct”. However, such formulas probably will not have a good distribution, and therefore would likely cause more collisions than otherwise, which will have a detrimental effect on performance.Here’s a quote from Effective Java 2nd Edition, Item 9: Always override
hashCodewhen you overrideequalsIt may not require a lot of mathematical power to evaluate how good your proposed hash function is, but why even bother? Why not just follow something that has been anecdotally proven to be adequate in practice?
Josh Bloch’s recipe
intvariable calledresult.inthashcodecfor each field:boolean, compute(f ? 1 : 0)byte, char, short, int, compute(int) flong, compute(int) (f ^ (f >>> 32))float, computeFloat.floatToIntBits(f)double, computeDouble.doubleToLongBits(f), then hash the resultinglongas in above.equalsmethod compares the field by recursively invokingequals, recursively invokehashCodeon the field. If the value of the field isnull, return 0.Arrays.hashCodemethods added in release 1.5.cintoresultas follows:result = 31 * result + c;Now, of course that recipe is rather complicated, but luckily, you don’t have to reimplement it every time, thanks to
java.util.Arrays.hashCode(Object[])(andcom.google.common.base.Objectsprovides a convenient vararg variant).See also
Object.hashCode()