為何重寫equals方法必須重寫hashCode方法,如何重寫hashCode方法

一旦重寫了equals方法,就一定要重寫hashCode方法。

hashCode方法的約定:

  1. 一個對象多次調(diào)用它的hashCode方法,應(yīng)當(dāng)返回相同的integer(哈希值)。
  2. 兩個對象如果通過equals方法判定為相等,那么就應(yīng)當(dāng)返回相同integer。相等對象必然導(dǎo)致相等hashCode。
  3. 兩個地址值不相等的對象調(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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容