一旦重寫了equals方法,就一定要重寫hashCode方法。
hashCode方法的約定:
- 一個對象多次調(diào)用它的hashCode方法,應(yīng)當(dāng)返回相同的integer(哈希值)。
- 兩個對象如果通過equals方法判定為相等,那么就應(yīng)當(dāng)返回相同integer。相等對象必然導(dǎo)致相等hashCode。
- 兩個地址值不相等的對象調(diào)用hashCode方法不要求返回不相等的integer,但是要求擁有兩個不相等integer的對象必須是不同對象。不相等hashCode必然是不相等對象導(dǎo)致。
在HashMap、HashTable中,put操作是先通過對象的hashCode取模運算后找到存儲位置的,如果位置不存在就直接插入,如果存在,就要判定equals方法返回值是否為true,為true說明兩個對象字面量是相等的,就覆蓋插入。如果為false,說明發(fā)生了hash沖突。
重寫hashCode方法的目標(biāo)是:不相等的對象盡可能有不同的hashCode,而且必須滿足的一個通用約定是:相等的對象必須具有相同的hashCode。
如果重寫了equals方法不去重寫hashCode方法,就會導(dǎo)致一種現(xiàn)象:相同的對象有不相等的hashCode,在HashMap機制下就會發(fā)生混亂。
重寫hashCode方法的示例:
public class HashCodeTest {
private String dishCode;
private boolean weighing;
private String categoryCode;
private boolean currentPrice;
private boolean discountable;
private int stopSell;
private int soldOut;
private boolean deal = false;
private List<DealGroup> dealGroupList;
...
get、set方法
...
@Override
public int hashCode() {
int result = dishCode != null ? dishCode.hashCode() : 0;
result = 31 * result +soldOut;
result = 31 * result +stopSell;
result = 31 * result + (currentPrice ? 1 : 0);
result = 31 * result + (weighing ? 1 : 0);
result = 31 * result + (categoryCode != null ? categoryCode.hashCode() : 0);
result = 31 * result + (dealGroupList != null ? dealGroupList.hashCode() : 0);
return result;
}
}
這里面為啥用個31來計算,而且很多人都是這么寫的,這是因為31是個神奇的數(shù)字,任何數(shù)n*31都可以被jvm優(yōu)化為(n<<5)-n,移位和減法的操作效率比乘法的操作效率高很多!
31對虛擬機的識別非常友好,對于虛擬機來說31 = 2^5 - 1