必須謹記:對於每一個類,重寫equals
方法時,必須重寫hashCode
方法。如果沒有遵照此規定,則在所有基於hash
計算的類中(如:HashMap
、HashSet
和HashTable
)都會出問題。
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