equals方法
public boolean equals(Object obj)
訓示其他某個對象是否與此對象“相等”。equals 方法在非空對象引用上實作相等關系:
- 自反性:對于任何非空引用值 x,x.equals(x) 都應傳回 true。
- 對稱性:對于任何非空引用值 x 和 y,當且僅當 y.equals(x) 傳回 true 時,x.equals(y) 才應傳回 true。
- 傳遞性:對于任何非空引用值 x、y 和 z,如果 x.equals(y) 傳回 true,并且 y.equals(z) 傳回 true,那麼 x.equals(z) 應傳回 true。
- 一緻性:對于任何非空引用值 x 和 y,多次調用 x.equals(y) 始終傳回 true 或始終傳回 false,前提是對象上 equals 比較中所用的資訊沒有被修改。
- 對于任何非空引用值 x,x.equals(null) 都應傳回 false。Object 類的 equals 方法實作對象上差别可能性最大的相等關系;即,對于任何非空引用值 x 和 y,當且僅當 x 和 y 引用同一個對象時,此方法才傳回 true(x == y 具有值 true)。
注意:當此方法被重寫時,通常有必要重寫 hashCode 方法,以維護 hashCode 方法的正常協定,該協定聲明相等對象必須具有相等的哈希碼。
參數:
obj - 要與之比較的引用對象。
傳回:
如果此對象與 obj 參數相同,則傳回 true;否則傳回 false。
實作高品質equals方法的訣竅
- 使用==操作符檢查“參數是否為這個對象的引用”。
- 使用instanceof操作符檢查“參數是否為正确的類型”。
- 把參數轉換為正确的類型。
- 對于該類中的每個“關鍵(significant)”域,檢查參數中的域是否與該對象中對應的域想比對。
- 當你編寫完成了equals方法之後,應該問自己三個問題:它是否是對稱的、傳遞的、一緻的?
一些告誡
- 覆寫equals時總要覆寫hashCode。
- 不要企圖讓equals方法過于智能。
- 不要将equals聲明中的Object對象替換為其他的類型。
hashCode方法
public int hashCode()
傳回該對象的哈希碼值。支援此方法是為了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。hashCode 的正常協定是:
在 Java 應用程式執行期間,在對同一對象多次調用 hashCode 方法時,必須一緻地傳回相同的整數,前提是将對象進行 equals 比較時所用的資訊沒有被修改。從某一應用程式的一次執行到同一應用程式的另一次執行,該整數無需保持一緻。
如果根據 equals(Object) 方法,兩個對象是相等的,那麼對這兩個對象中的每個對象調用 hashCode 方法都必須生成相同的整數結果。
如果根據 equals(java.lang.Object) 方法,兩個對象不相等,那麼對這兩個對象中的任一對象上調用 hashCode 方法不 要求一定生成不同的整數結果。但是,程式員應該意識到,為不相等的對象生成不同整數結果可以提高哈希表的性能。
實際上,由 Object 類定義的 hashCode 方法确實會針對不同的對象傳回不同的整數。(這一般是通過将該對象的内部位址轉換成一個整數來實作的,但是 JavaTM 程式設計語言不需要這種實作技巧。)
傳回:
此對象的一個哈希碼值。
幾點注意
- 要想使hashCode()實用,它必須速度快,并且必須有意義。也就是說,它必須基于對象的内容生成散列碼。散列碼不必是獨一無二的(應該關注生成速度,而不是唯一性),但是通過hashCode()和equals(),必須能夠完全确定對象的身份。
- 散清單的生成範圍并不重要,隻要是int就好
- 好的hashCode()應該生成均勻分布的散列碼。如果散列碼都集中在一塊,那麼hashMap後者hashSet在某些區域的負載會很重,這樣就不如分布均勻的散列函數快。
如何生成一份像樣的hashCode():
- 給int變量result賦予某個非零常量
- 為對象每個有意義的域f(即每個可以做equals操作的域)計算出一個int散列碼c
- 合并計算得到的散列碼 result= 31*result+c;
- 傳回result
- 檢查hashCode()最後生成的結果,確定相同的對象有相同的散列碼