Java對象默認的equals方法都是比較兩個對象的地址的。
如果要重寫equals方法,要滿足一下四點:
Reflexive(自反性):即 x.equals(x)必須是true
Symmetric(對稱性):即如果 x.equals(y)返回true,那麼y.equals(x)也必須返回true
Transitive(傳遞性):即如果 x.equals(y)返回true, y.equals(z)也返回true,那麼x.equals(z)也必須返回true
Consistent(一致性):即多次調用 x.equals(y)返回的結果必須保持一致。
非空特性:即對於非空對象x,x.equals(null)總是返回false
hashCode這個方法是爲了在使用HashMap HashSet LinkedHashMap LinkedHashSet等數據結構的時候,爲了更快速的找到key而產生的,其中通過求key的hashcode迅速找到對應的bucket位置,然後再通過equals方法來找到bucket所指向的鏈表裏面的對應的value。這也就是爲什麼在重寫equals方法是也要重寫hashCode方法,這是爲了讓equals返回true的時候兩個對象的hashCode必須相等,但是反之則不一定了。
那麼如何寫出有效的hashCode函數呢?其實最重要的是要提取出對象的重要屬性。Java大神Joshua Bloch曾經在他的大作《Effective Java》這樣定義一個有效的hashCode函數的產生過程:
1、去一個非零常量,比如17,將它賦給變量result
2、爲每一個在equals方法裏面用到過的屬性計算它們的hash值c:
-
如果屬性變量是bool值:
c = (f ? 0 : 1)
;
-
byte, char, short 或者 int:
c = (int)f
; -
long:
c = (int)(f ^ (f >>> 32))
; -
float: c =
Float.floatToIntBits(f)
; -
double:c =
Double.doubleToLongBits(f),然後執行之前處理long的步驟
; -
object: c=(f == null?0:f.
hashCode())
; - array: 將數組裏面的值按照上面的處理方法處理
3、將所有的值以下形式計算
result = 37 * result + c
4、返回結果