【Effective Java】條9:重寫equals方法時必須重寫hashCode 方法

必須謹記:對於每一個類,重寫equals方法時,必須重寫hashCode方法。如果沒有遵照此規定,則在所有基於hash計算的類中(如:HashMapHashSetHashTable)都會出問題。

hashCode約定

Object規範中有這樣的約定:

  • 在程序相同執行過程中多次調用同個對象,哈希值必須返回相同。但不是相同調用過程則不必相同;
  • 如果兩個對象調用equals()方法相同,則hashCode()方法返回值必須相同;
  • 如果兩個對象調用equals()方法不相同,並不需要兩個對象的哈希值不相同。但是開發者必須意識到,不同的對象產生不同的哈希值可以提高像HashTable這樣類的性能

重寫hashCode方法

若需要重寫hashCode方法,可以參照如下步驟:
1. 取個非0的常量值,賦值給result。譬如,result=17
2. 對類中每一個關鍵屬性(equals方法中用到的屬性)f,作如下處理
1). 計算屬性f的哈希值,賦值給c

    a. `f`爲`boolean`類型,`c = f ? 1 : 0`

    b. `f`爲`byte`、`char`、`short`、`int`類型,`c = (int)f`

    c. `f`爲`long`類型,`c = (int)(f ^ (f >>> 32))`

    d. `f`爲`float`類型,`c = Float.floatToIntBits(f)`

    e. `f`爲`double`類型,首先`temp = Double.doubleToLongBits(f)`,之後按照2.1).c步驟來計算`c = (int)(temp ^ (temp >>> 32))`

    f. `f`爲對象引用,並且`equals`方法是通過迭代`f`的屬性進行判斷的,則`hashCode`方法也必須迭代計算`f`中的`hashCode`值。若需要更復雜的計算,則爲此屬性計算個範式,然後針對這個範式調用`hashCode`。如果屬性爲`null`,一般返回0
    g. `f`爲數組,則需將每一個元素單獨按2.1).(a-f)步驟處理,然後按照2.2)將哈希值組合起來。若數組中每個元素都很重要,可以利用`Arrays.hashCode`方法計算
2). 將2.1)中計算的`c`合併到`result`中:`result = 31 * result + c`

3. 返回result

發佈了98 篇原創文章 · 獲贊 180 · 訪問量 40萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章