All relevant fields from the object should be included in the hashCode method. Derived fields may be excluded. In general, any field used in the equals method must be used in the hashCode method.
Proposed in Josh Bloch's Effective Java in item 8. The best thing is to look it up there because the author explains there why the approach is good.
A short version
- Create a
int resultand assign a non-zero value. - For every field
ftested in theequals()method, calculate a hash codecby:- If the field f is a
boolean: calculate(f ? 0 : 1); - If the field f is a
byte,char,shortorint: calculate(int)f; - If the field f is a
long: calculate(int)(f ^ (f >>> 32)); - If the field f is a
float: calculateFloat.floatToIntBits(f); - If the field f is a
double: calculateDouble.doubleToLongBits(f)and handle the return value like every long value; - If the field f is an object: Use the result of the
hashCode()method or 0 iff == null; - If the field f is an array: see every field as separate element and calculate the hash value in a recursive fashion and combine the values as described next.
- If the field f is a
- Combine the hash value
cwithresult:result = 37 * result + c - Return
result
This should result in a proper distribution of hash values for most use situations.
@Override
public int hashCode() {
// Start with a non-zero constant. Prime is preferred
int result = 17;
// Include a hash for each field.
// Primatives
result = 31 * result + (booleanField ? 1 : 0); // 1 bit » 32-bit
result = 31 * result + byteField; // 8 bits » 32-bit
result = 31 * result + charField; // 16 bits » 32-bit
result = 31 * result + shortField; // 16 bits » 32-bit
result = 31 * result + intField; // 32 bits » 32-bit
result = 31 * result + (int)(longField ^ (longField >>> 32)); // 64 bits » 32-bit
result = 31 * result + Float.floatToIntBits(floatField); // 32 bits » 32-bit
long doubleFieldBits = Double.doubleToLongBits(doubleField); // 64 bits (double) » 64-bit (long) » 32-bit (int)
result = 31 * result + (int)(doubleFieldBits ^ (doubleFieldBits >>> 32));
// Objects
result = 31 * result + Arrays.hashCode(arrayField); // var bits » 32-bit
result = 31 * result + referenceField.hashCode(); // var bits » 32-bit (non-nullable)
result = 31 * result + // var bits » 32-bit (nullable)
(nullableReferenceField == null
? 0
: nullableReferenceField.hashCode());
return result;
}
OR
@Override
public int hashCode(){
return Objects.hashCode(this.firstName, this.lastName);
}
OR
String name;
int age;
boolean smoker;
...
public int hashCode() {
// you pick a hard-coded, randomly chosen, non-zero, odd number
// ideally different for each class
return new HashCodeBuilder(17, 37).
append(name).
append(age).
append(smoker).
toHashCode();
}
}
If required, the superclass hashCode() can be added using appendSuper(int).
No comments:
Post a Comment