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 called result
- Compute an
int
hashcode c
for each field f
that defines equals
:
- 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
, compute Float.floatToIntBits(f)
- If the field is a
double
, compute Double.doubleToLongBits(f)
, then hash the resulting long
as in above
- If the field is an object reference and this class's
equals
method compares the field by recursively invoking equals
, recursively invoke hashCode
on the field. If the value of the field is null
, 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
- Combine the hashcode
c
into result
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...)
.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…