Use the same fields in constructing a hash code as are used in the (overloaded) equals method. This is required!
For each such field, calculate a hashcode just for that field
(let's call them fieldHash1, fieldHash2, ...).
The way the field hash code is calculaed depends on the type of
the field f
:
type of field | hash code formula | |
---|---|---|
boolean | fieldHash = f ? 0 : 1 | |
any integer type except long | fieldHash = (int) f | |
long | fieldHash = (int) (f ^ (f >>> 32)) | |
float | fieldHash = Float.floatToIntBits( f ) | |
double | int v=Double.doubleToLongBits(f) fieldHash = (int) (v ^ (v >>> 32)) |
|
any Object reference | fieldHash = f.hashCode() |
For collections or arrays, treat each item as a separate field.
Finally, combine the obtained fieldHash values into the result so far. The result should be initialized to a random value. Experience has shown that prime numbers work well, something like:
int result = 17;
To combine each file hash code into the result:
result = 37 * result + fieldHash1; result = 37 * result + fieldHash2; result = 37 * result + fieldHash3; ... return result;
class Person { private final String lastName, firstName; private int age; private final long SSN; ... public boolean equals (Object o ) { if ( o instanceof Person ) // Note this is false if o == null { Person p = (Person) o; return (this.lastName.equals(p.lastName) && this.SSN == p.SSN); } return false; } public int hashCode () { int result = 17; // 17 is an arbitrary value result = 37 * result + (int) (SSN ^ (SSN >>> 32)) // so is 37 result = 37 * result + lastName.hashCode(); return result; }
If a hash code for some object seems time consuming to compute, you may not use it at all, or you may need it many times. The way to deal with this situation is known as lazy initialization. Basically, you only calculate the value once, the first time the hashCode method is invoked on that object. Once calculated you store the hash code in a property:
class Foo { ... private volatile int hashCode = 0; public int hashCode() { if ( hashCode == 0 ) { int result = 17; // 17 is arbitrary value result = 37 * result + field1hash; result = 37 * result + field2hash; ... hashCode = result; } return hashCode; } }