Hi. I'm wondering what is the best practice for writing #hashCode() method in java. Good description can be found here. Is it that good?
Yes. But do not skip the conceptual explanations and jump to the code examples . Before know how to write the method, you must understand what the hashcode is - and there it is explained.
It's good, as @leonbloy says, to understand it well. Even then, however, one "best" practice is to simply let your IDE write the function for you. It won't be optimal under some circumstances - and in some very rare circumstances it won't even be good - but for most situations, it's easy, repeatable, error-free, and as good (as a hash code) as it needs to be. Sure, read the docs and understand it well - but don't complicate it unnecessarily.
If it is possibly I basically compare the fields in the class, and xor the hash-codes of the fields in the class.
A great reference for an implementation of hashCode()
is described in the book Effective Java. After you understand the theory behind generating a good hash function, you may check HashCodeBuilder from Apache commons lang, which implements what's described in the book. From the docs:
This class enables a good hashCode method to be built for any class. It follows the rules laid out in the book Effective Java by Joshua Bloch. Writing a good hashCode method is actually quite difficult. This class aims to simplify the process.
Here's a quote from Effective Java 2nd Edition, Item 9: Always override hashCode
when you override equals
While the recipe in this item yields reasonably good hash functions, it does not yield state-of-the-art hash functions, nor do Java platform libraries provide such hash functions as of release 1.6. Writing such hash functions is a research topic, best left to mathematicians and computer scientists. [...Nonetheless,] the techniques described in this item should be adequate for most applications.
Josh Bloch's recipe
- Store some constant nonzero value, say 17, in an
int
variable calledresult
. - Compute an
int
hashcodec
for each fieldf
that definesequals
:- If the field is a
boolean
, compute(f ? 1 : 0)
- If the field is a
byte, char, short, int
, compute(int) f
- If the field is a
long
, compute(int) (f ^ (f >>> 32))
- If the field is a
float
, computeFloat.floatToIntBits(f)
- If the field is a
double
, computeDouble.doubleToLongBits(f)
, then hash the resultinglong
as in above. - If the field is an object reference and this class's
equals
method compares the field by recursively invokingequals
, recursively invokehashCode
on the field. If the value of the field isnull
, return 0. - If the field is an array, treat it as if each element is a separate field. If every element in an array field is significant, you can use one of the
Arrays.hashCode
methods added in release 1.5.
- If the field is a
- Combine the hashcode
c
intoresult
as 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[])
.
@Override public int hashCode() {
return Arrays.hashCode(new Object[] {
myInt, //auto-boxed
myDouble, //auto-boxed
myString,
});
}
com.google.common.base.Objects
provides a convenient vararg variant.