爲什麼重寫equals()就必須重寫hashcode()

JVM是從內存角度看對象的,內存一樣的對象纔算是相等的,所以,內存的唯一性決定了對象只能是“自己和自己纔是相等的”。

Java的“==”規則是個內存判斷,默認的equals()也使用了“==”規則:

/**
 * 該方法應該滿足五個條件:
 * 1、自反性:任意對象x,x.equals(x)==true
 * 2、對稱性:任意對象x、y,如果x.equals(y)==true,那麼,y.equals(x)==true
 * 3、傳遞性:任意對象x、y、z,如果x.equals(y)==true,並且y.equals(z)==true,那麼,x.equals(z)==true
 * 4、一致性:任意對象x、y,如果對象中用於等價比較的信息沒有改變,那麼x.equals(y)返回的結果應該始終一致,要麼true,要麼false
 * 5、任何不是null的x,x.equals(null)一定返回false
 */
public boolean equals(Object obj) {
    return (this == obj);
}

hashcode()方法是計算對象的散列碼,在散列數據結構當中用來定位對象的位置。常用的HashMap就是個散列結構。

每個對象都有一個散列碼,在對象剛剛被創建的時候就生成好了,以後都不會再發生變化,不同對象的散列碼可能會相同,這就是散列衝突問題。

基於內存視角的JVM規則,可以保證:在散列數據結構當中,相等的對象可以被散列到相同的位置,因爲對象只能和自己相等!

如果我們重寫了equals()方法,就相當於改變了JVM默認的內存視角規則,開始從我們的業務視角去看待對象相等的問題了。這樣就會導致了一個現象:不同內存的兩個對象A和B,可以是相等的!這與JVM默認的內存規則是相違背的。

如果我們不去重寫hashcode(),使用JVM默認規則可以預見:A和B兩個對象的散列碼是不一樣的(有可能一樣,概率很低)。
這就會出現一個很嚴重的問題:在散列數據結構當中,相等的對象被散列到了不同的位置(有可能相同,概率很低)!

散列數據結構的理論遭到了嚴重破壞!後果就是使用HashMap這些基於散列結構的類會出錯,導致不可預知的錯誤結果,程序就不可能正確執行。

所以,改變了equals()規則,就需要改變hashcode()規則,這也是重寫hashcode()方法的意義所在,保證散列數據結構理論的正確性:相等對象可以被散列到相同的位置!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章