hashcode和equals的讀書筆記

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、返回結果

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章