天天看點

equals()方法和hashCode()的使用

1. 原生equals()方法的内容:

public boolean equals(Object obj) {

    return (this == obj);

}

  equals方法在其内部是調用了"==",是以說在不重寫equals方法的情況下,equals方法是比較兩個對象是否具有相同的引用,即是否指向了同一個記憶體位址。

而在業務系統中,有時候需要的并不是一種嚴格意義上的相等,而是業務上的對象相等。比如:如果兩個對象中的id相等,那麼就認為這兩個對象是相等的。

2.重寫equals()方法,需要遵守的通用約定

   1>自反性

       對于任意非null的引用值x,x.equals(x)必須傳回true。

   2>對稱性

      對于任意非null的引用值x、y,當且僅當y.equals(x)傳回true時,x.equals(y)必須傳回true。

   3>一緻性

      對于任意非null的引用值x、y,隻要equals方法的比較操作在對象中所用的資訊沒有發生改變,那麼多次調用x.equals(y)應該        一緻的傳回true或false。

   4>傳遞性

      對于任意非null的引用值x、y、z,如果x.equals(y)傳回true,并且y.equals(z)傳回true,那麼x.equals(z)必須傳回true。

      對于任意非null的引用值x,x.equals(null)必須傳回false。

   5> 非空性

      對于任意null的引用值x,x.equals(null) 一定是false。

3.hashCode()

   原生寫法:

public native int hashCode();
           

hashCode是一個本地方法,他傳回的是這個對象的記憶體位址。   

這個方法傳回對象的散列碼,傳回值是int類型的散列碼。

   對象的散列碼是為了更好的支援基于哈希機制的Java集合類,例如 Hashtable, HashMap, HashSet 等。

   重寫hashCode方法時除了上述一緻性約定,還有以下幾點需要注意:

 (1)傳回的hash值是int型的,防止溢出。

 (2)不同的對象傳回的hash值應該盡量不同。(為了hashMap等集合的效率問題)

 (3)《Java程式設計思想》中提到一種情況

“設計hashCode()時最重要的因素就是:無論何時,對同一個對象調用hashCode()都應該産生同樣的值。如果在講一個對象用put()添加進HashMap時産生一個hashCdoe值,而用get()取出時卻産生了另一個hashCode值,那麼就無法擷取該對象了。是以如果你的hashCode方法依賴于對象中易變的資料,使用者就要當心了,因為此資料發生變化時,hashCode()方法就會生成一個不同的散列碼”。

4. 重寫equals()方法必須重寫hashCode()方法

    原因:hashCode()方法在Object規範中的通用約定第二條,相等的對象必須具有相等的散列碼。

    1>在應用運作期間,隻要對象的equals方法的比較操作所用到的資訊沒有被修改,那麼多次調用該對象的equals方法應該始終如一的傳回同一個整數。在同一個應用程式的多次執行過程中,每次執行equals方法所傳回的整數可以不一緻。

    2>如果兩個對象使用equals(Object)方法比較是相等的,那麼調用這兩個對象中的任意一個對象的hashCode方法都必須産生相同的一個整數結果。

    3>如果兩個對象使用equals(Object)方法比較是不相等的,那麼調用這兩個對象中的任意一個對象的hashCode方法,則不一定要産生不同的整數結果。如果給不同的對象産生不同的hash碼,有可能提高散清單性能(比如往HashMap中添加資料時,具體添加到哪個桶中,就是根據(table.length - 1) & hash來計算的)。

如果一個類重寫了equals方法但是沒有重寫hashCode方法,那麼該類無法結合所有基于散列的集合(HashMap,HashSet)一起正常運作。

5.寫法

equals()方法和hashCode()的使用

31*N可以被編譯器優化為左移5位後減1即31*N =(N<<5)-1,有較高的性能。使用31的原因可能是為了更好的配置設定hash位址,并且31隻占用5bits! 是以從效率上 它是2的5次減1,對計算機來說2的乘除操作隻需要做位移操作,例如*32就是左移5位。 也就是說31對計算機的角度來說運算更快、切占記憶體不多不少,而且形成慣例,虛拟機甚至都專門對他做了優化。是以常用31做系數算hashcode