只要覆寫equals,就必須覆寫hashCode

只要覆寫equals,就必須覆寫hashCode
參考文獻:在這裏插入圖片描述
阿里的開發手冊中是寫了這麼兩句話:
(1)因爲Set 存儲的是不重複的對象,依據 hashCode和equals進行判斷,所以 Set 存儲的對象必須覆 寫這兩個方法。
(2)如果自定義對象作爲Map 的鍵,那麼必須覆寫hashCode 和equals
下面我來解釋一下:
先看這段代碼

public static void main(String[] args) {
        Set set = new HashSet();
        String str1 = new String("Evan");
        String str2 = new String("Evan");
        set.add(str1);
        set.add(str2);
        System.out.println(str1 == str2);
        System.out.println(str1.equals(str2));
        System.out.println(set.size());
    }

那麼它打印的結果是多少呢
false
true
1
很明顯str1和str2是不同的兩個的對象,但是set存的值卻只有一個這是爲什麼呢,因爲string重寫了equals和hashcode方法

        System.out.println(str1.hashCode());
        System.out.println(str2.hashCode());
     	2172094
		2172094

當我們往一個空的Set集合中加入數據時,第一次加入的數據會直接加入到集合中,從第一個往後所有要加入的數據會和集合裏的數據進行比較。而且會先比較當前加入數據的hashCode()的值是否在set集合中存在,如果沒有重複,那麼就會認爲這是兩個不同的數據 就會直接加入。但是如果hashCode()的值相同,就會再調用equals()方法來比較,如果也相同那麼就認爲是一個數據,否則就是兩個數據。而且當hashCode()的值不同是就不會繼續調用equals()了。
上面代碼的str1和str2因爲string重寫了equals和hashcode兩者比較都是相同的,故set去重,只存入了一個值。
解釋一下爲何先要比較hashCode()值是否相等,然後再用equals()進行比較。
hashCode()方法和equal()方法的作用在Java裏都是用來對比兩個對象是否相等一致。假如用equals(),那麼存儲一個元素就要跟已存在的所有元素比較一遍,比如已存入100個元素,那麼存101個元素的時候,就要調用equals方法100次,重寫的equal()方法底層實現裏一般比較複雜,從而效率就比較低,而利用hashCode()進行對比,則只要生成一個hash值進行比較就可以了,效率很高。但是利用hashCode()進行比較時會存在一個問題,有兩個不相等的數據在生成hash值時偶爾會相等。所以需要再次調用equal()方法進行比較。這樣比較既能提高效率又能確保準確性。
再說一下hashset存值的順序:hashset存值,首先他會判斷該對象的hash值在hashset集合中是否存在(自定義對象要自己實現hashcode方法和equals方法,String等已經實現不需要自己再實現),如果不存在則存入集合(這個時候就用到它的數據結構了,數組!其實存入的就是數組),如果存在相同的hash值,即哈希碰撞,則判斷equals方法,相同就不存,如果不同,則證明,該集合中存在與該對象相同的hash值但是值不同的對象,就會再判斷它是否有樹結點,有就轉換爲紅黑樹,否則,就存入鏈表,如果鏈表值(即哈希碰撞值)大於8就會轉換爲紅黑樹。
總而言之,每當覆蓋equals方法時都必須覆蓋hashCode,否則程序將無法運行,hashCode的方法必須遵守Object規定的通用約定,並且必須完成一定的工作,將不相等的散列碼分配給不相等的實例。

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