您的位置:首页 > 其它

(Item 8) Override hashCode when you override equals()

2007-05-11 00:23 239 查看
(Item 8) Override hashCode when you override equals()
Incentive
public final class PhoneNumber {
private final short areaCode;
private final short exchange;
private final short extension;

public PhoneNumber(int areaCode, int exchange,
int extension) {
this.areaCode = (short) areaCode;
this.exchange = (short) exchange;
this.extension = (short) extension;
}

public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof PhoneNumber))
return false;
PhoneNumber pn = (PhoneNumber)o;
return pn.extension == extension &&
pn.exchange == exchange &&
pn.areaCode == areaCode;
}
//...
}
Map m = new HashMap();
m.put(new PhoneNumber(408, 867, 5309), "Jenny");
m.get(new PhoneNumber(408, 867, 5309)) return null instead of "Jenny" !!!

Cause: Two equal instance have unequal hashcode

// Example of bad hasCode
public int hashCode() { return 42; }
Why? Because every object hashes to the same bucket, and hash tables degenerate to linked lists

Recipe for good hashCode() function
1. Store some constant nonzero value, say 17, in an int variable called result.
2. For each significant field f in your object (each field taken into account by the equals method, that is), do the following:
a. Compute an int hash code c for the field:
i. If the field is a boolean, compute (f ? 0 : 1).
ii. If the field is a byte, char, short, or int, compute (int)f.
iii. If the field is a long, compute (int)(f ^ (f >>> 32)).
iv. If the field is a float compute Float.floatToIntBits(f).
v. If the field is a double, compute Double.doubleToLongBits(f), and then hash the resulting
long as in step 2.a.iii.
vi. 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 a more complex comparison is required, compute a “canonical representation” for this field and invoke on the canonical representation. If the value of the field is null, return 0 (or some other constant, but 0 is traditional).
vii. If the field is an array, treat it as if each element were a separate field. That is, compute a hash code for each significant element by applying these rules recursively, and combine these values as described in step 2.b.
b. Combine the hash code c computed in step a into result as follows:
result = 37*result + c;
3. Return result.
4. When you are done writing the hashCode method, ask yourself whether equal instances have equal hash codes. If not, figure out why and fix the problem.

// Sample hashCode
//Lazily initialized, cached hashCode
private volatile int hashCode = 0; // (See Item 48)

public int hashCode() {
if (hashCode == 0) {
int result = 17;
result = 37*result + areaCode;
result = 37*result + exchange;
result = 37*result + extension;
hashCode = result;
}
return hashCode;
}

Do not be tempted to exclude significant parts of an object from the hash code computation to improve performance.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: