(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" !!!
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.
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 hasCodepublic 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.
相关文章推荐
- Effective Java 英文 第二版 读书笔记 Item 9:Always override hashCode when you override equals
- Always override hashCode when you override equals
- Effective Java 09 Always override hashCode when you override equals
- Why we should overwrite the hashCode() when we overwrite the equals()
- Why always override hashcode() if overriding equals()?
- What's the effect of hashCode() & equals() when adding object to List/Set/Map
- override the hashcode and equals method in java
- @EqualsAndHashCode()注解详解
- java 中在Lab2_实验 中遇到的问题 关于equals hashcode 和==
- Java hashcode 与 equals的关系
- Equals and Hash Code in Java(Sun认证重点试题)
- Working with hashCode and equals methods in java
- Java equals() and hashCode() Contract
- Effective Java 3rd 条目11 当你覆写equals时每次都覆写hashCode
- java hashCode() equals()
- How to resolve mysql problem when you get code 2003(10061) and 1130
- Effective Java 英文 第二版 读书笔记 Item 8:Obey the general contract when overriding equals
- java继承中的 equals + hashCode+toString
- Java hashCode() 和 equals()的若干问题解答
- JAVA 基础之 equals and HashCode