Java自帶容器類的equals和hashCode方法

java中有三大主要的容器類:listsetmap。他們都是interface,在這三大容器類下面分別有AbstractListAbstractSetAbstractMap這三個抽象類去實現他們,他們幾乎實現了對應接口中的所有方法(有少數方法沒有實現,仍然是abstract的)。其中他們實現的主要的方法就是hashCodeequals方法(toString方法不一定在這些類中實現的,因爲他們有的不是直接實現對應接口的,而是通過繼承AbstractCollection這個抽象類來實現接口的,toString方法有的是在抽象類中實現的,比如AbstractList就是繼承了AbstractCollection的抽象類)。下面我們就來分別的講解一下他們內部是如何實現hashCodeequals方法的:

 

首先我們需要說明的是他們的實現都是有效的,即他們的實現都能夠保證下面的推導成立: a.equals(b) =》 a.hashCode() = b.hashCode()

上面這個是一個充分非必要條件(AbstractSet對於equalshashCode的實現就是一個例子),即a.hashcode() = b.hashcode() =》 a.equals(b)是不對的。

所以有了上面的保證,我們以後就可以放心大膽的使用容器類(凡是繼承了AbstractListAbstractSet或者AbstractMap的容器類),而不用擔心他們的equalshashcode重新的問題了,而且java的設計者也是不希望我們去重新他們辛辛苦苦設計好的equalshashcode方法的,我們自己貿貿然的重新可能會導致不必要的錯誤,所謂費力不討好。比如最常用的就是將一個Set(比如HashSet)作爲元素放在另一個Set(比如HashSet)中去,我們就可以直接使用,而不用擔心因爲hashcodeequals重寫的問題造成的邏輯錯誤。

 

下面我們就來看看java的設計者是如何重新這些方法的:

 

equals()

(a.equals(b)true)

hashCode()

(hashCode()的算法)

AbstractList

1.ab都是List的子類

2.a.size()b.size()相等

3. a中和b中元素必須對應相等,即a中和b中下標相等的元素必須相等(即調用元素本身的equals方法返回true

list中每個元素的hashCode利用特殊的hash算法加起來,詳細代碼可以參考java源碼。

AbstractSet

1. ab都是Set的子類

2. a.size()b.size()相等

3. a中包含b中所有元素,由於Set是不考慮位置順序的,所以我們不要求位置一樣。由於有了第二條的限制,所以這條就保證了ab一定含有相同的元素,當然比較ab中的元素是否相等我們調用的也是元素本身的equals方法,返回true就表示兩個元素相等。

將所有非null元素的hash code加起來,當然元素的hash code是通過調用元素的hashCode方法獲得的。

AbstractMap

1. ab都是Map的子類

2. a.size()b.size()相等

3. a中包含的mappingb中包含的mapping是相同的,即

a.entrySet().equals(b.entrySet()),具體說來就是a中的key setb中的key set是相等的,並且相同key對應的值也是相等的。值的相等都是通過equals方法判斷的。

Map中所有Entry對象的hash code的和(Entry對象的hash code通過調用他們自己的hashCode方法獲得)。而Entry類的定義是Entry<K,V>Map中起到存放鍵值對的作用,Entry<K, V>hash code的算法是:

return 

(key   == null ? 0 :   key.hashCode()) ^

(value == null ? 0 : value.hashCode());

 

結語:愉快的享受java工程師給我們帶來的便利吧。

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