What is a best practice of writing hash function in java?
Solution 1
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.
Solution 2
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,
});
}
As of Java 7 there is a convenient varargs variant in java.util.Objects.hash(Object...)
.
Denys S.
We keep moving forward, opening new doors, and doing new things, because we're curious and curiosity keeps leading us down new paths. (Walt Disney) Imagination is more important than knowledge. For knowledge is limited to all we now know and understand, while imagination embraces the entire world, and all there ever will be to know and understand. (Albert Einstein)
Updated on July 09, 2022Comments
-
Denys S. almost 2 years
I'm wondering what is the best practice for writing #hashCode() method in java. Good description can be found here. Is it that good?
-
Denys S. about 14 yearsYeah, not an optimal solution when using entities in EJB or alike cases.