為什麼重寫equal方法的時候要重寫hashcode()方法?
面試官可能會問你:
“你重寫過
hashCode()
和equals()
麼?為什麼重寫equals()
時必須重寫hashCode()
方法?”
hashCode() 有什麼用?
hashCode()
的作用是獲取雜湊碼(int
整數),也稱為雜湊碼。這個雜湊碼的作用是確定該物件在雜湊表中的索引位置。
hashCode()
定義在 JDK 的 Object
類中,這就意味著 Java 中的任何類都包含有 hashCode()
函式。另外需要注意的是: Object
的 hashCode()
方法是本地方法,也就是用 C 語言或 C++ 實現的,該方法通常用來將物件的記憶體地址轉換為整數之後返回。
為什麼要有 hashCode?
我們以“HashSet
如何檢查重複”為例子來說明為什麼要有 hashCode
?
下面這段內容摘自我的 Java 啟蒙書《Head First Java》:
當你把物件加入
HashSet
時,HashSet
會先計算物件的hashCode
值來判斷物件加入的位置,同時也會與其他已經加入的物件的hashCode
值作比較,如果沒有相符的hashCode
,HashSet
會假設物件沒有重複出現。但是如果發現有相同hashCode
值的物件,這時會呼叫equals()
方法來檢查hashCode
相等的物件是否真的相同。如果兩者相同,HashSet
就不會讓其加入操作成功。如果不同的話,就會重新雜湊到其他位置。這樣我們就大大減少了equals
的次數,相應就大大提高了執行速度。
其實, hashCode()
和 equals()
都是用於比較兩個物件是否相等
那為什麼 JDK 還要同時提供這兩個方法呢?
這是因為在一些容器(比如 HashMap
、HashSet
)中,有了 hashCode()
之後,判斷元素是否在對應容器中的效率會更高(參考新增元素進HastSet
的過程)!
我們在前面也提到了新增元素進HastSet
的過程,如果 HashSet
在對比的時候,同樣的 hashCode
有多個物件,它會繼續使用 equals()
來判斷是否真的相同。也就是說 hashCode
那為什麼不只提供 hashCode()
方法呢?
這是因為兩個物件的hashCode
值相等並不代表兩個物件就相等。
那為什麼兩個物件有相同的 hashCode
值,它們也不一定是相等的?
因為 hashCode()
所使用的雜湊演算法也許剛好會讓多個物件傳回相同的雜湊值。越糟糕的雜湊演算法越容易碰撞,但這也與資料值域分佈的特性有關(所謂雜湊碰撞也就是指的是不同的物件得到相同的 hashCode
)。
總結下來就是 :
- 如果兩個物件的
hashCode
值相等,那這兩個物件不一定相等(雜湊碰撞)。 - 如果兩個物件的
hashCode
值相等並且equals()
方法也返回true
,我們才認為這兩個物件相等。 - 如果兩個物件的
hashCode
值不相等,我們就可以直接認為這兩個物件不相等。
為什麼重寫equal方法的時候要重寫hashcode()方法?
其實不一定的,只是許多容器類,如 HashMap、HashSet 都依賴於 hashcode 與 equals 的規定。
為什麼需要重寫hashcode()方法?
由於在hashMap中在put時,雜湊函式根據它的雜湊值找到對應的位置,如果該位置有元素,首先會使用hashCode方法判斷,如果沒有重寫hashCode方法,那麼即使倆個物件屬性相同hashCode方法也會認為他們是不同的元素,又因為Set是不可以有重複的,所以這會產生矛盾,那麼就需要重寫hashCode方法。