關于hashCode與equals方法的說明:

yanguz123 13年前發布 | 2K 次閱讀

關于hashCodeequals方法的說明:

1)對于一個程序的一次執行過程中,同一個對象的hashCode計算的結果一定相同,但是對于同一個程序的不同執行過程中,不要求其hashCode一定相同。

 2)對于兩個對象,如果使用equals方法比較,結果為true,那么這兩個對象的hashCode值一定相同

3)對于兩個對象,如果使用equals方法比較,結果為false,那么這兩個對象的hashCode值不要求一定不同(但是如果不同可以提高程序性能)

 

當我們向HashSet中add對象,它首先調用它的HashCode方法,得到這個HashCode的返回整數值,這個整數值就會映射到set里面的某一個位置。如果這個對象里沒有對象存在,就把這個對象直接放發哦set里面;如果這個位置已經有對象存在了,這個時候就用equals方法比較這兩個方法,如果比較結果相同,就不進行插入。比如下面問題

 

Set set new HashSet();

set.add("zhangsan");

set.add("lisi");

set.add("wangwu");

set.add("zhangsan");

這個最后一個set.add("zhangsan");是無法插入成功的,因為String重寫了Object的equlas和HashCode方法,按照String的HashCode方法,相同的字符串的HashCode一定是一樣的

下面詳細分析最后一個set.add("zhangsan")具體插入過程

1.首先根據"zhangsan"調用HashCode方法,獲得一個返回值

2.Set根據這個返回值獲得一個位置

3.查找這個位置上是否有對象,結果發現有一個對象。值也是“zhangsan”

4.對兩個對象調用equals方法,由于String重寫了equals方法,這個方法返回true。

所以最后插入失敗。

 

再看下面這個例子

People p1 new People("zhangsan");

People p2 new People("lisi");

People p3 new People("wangwu");

People p4 new People("zhangsan");

People p5 new People("zhangsan");

 

set.add(p1);

set.add(p2);

set.add(p3);

set.add(p4);

set.add(p5);

 

由于People 繼承自Object類,且沒有重寫equals和HashCode方法,而object的HashCode方法每個不同對象的返回值都是不同的,所以第一步查找插入位置的時候各個對象的位置就不一樣,所以一定可以插入進去。

 

Object類的HashCode實際上根據對象的地址生成的,所以不同對象的HashCode必然不一樣,但是String的HashCode是根據字符串的內容和大小生成的,所以相同字符串的HashCode是一樣的。

 

 

HashSet和HashMap

1. HashSet底層采用HashMap實現

HashMap內部是無序的,取出的順序和放入的順序沒有關系。java提供了TreeMap是有序的。

 

2. 這個HashMap的key就是放進HashSet中的對象,而value就是一個Object類型的對象,這個value我們不關心它到底是什么,事實上這是一個隨意生成的object對象。

 

3. 當調用HashSet的add方法時,實際上是向HashMap中增加了一行(key-value對),該行的key就是向HashSet中增加的那個對象,該行的value就是一個Object類型的常量

 

4. HashMap底層采用數組維護,這個數組中每個元素實際上又是一個單鏈表,擁有相同HashCode值的key對應的鍵值對就放在這個單鏈表中。

當調用add方法,首先根據這個key的HashCode方法算出一個int值,這個int對應到數組的一個位置,由于可能會有不同的key有相同的HashCode值,所以這個位置上存放的是一個鏈表。然后這個新加進來的key會和這個鏈表中的每個元素的key調用equals方法進行比較。如果返回true,就用這個新的鍵值對替換掉鏈表中原來那個老的鍵值對。如果找到最后都沒有返回true,就把這個新的鍵值對添加到鏈表的頭。(之所以不添加到鏈表的尾是為了提高檢索效率,新添加的數據被檢索的可能性要高。)

 

5. 調用增加的那個對象的hashCode方法,來得到一個hashCode值,然后根據該值計算出一個數組的下表索引(計算出數組中的一個位置)

 

6. 將準備增加到Map中的對象與該位置上的對象進行比較(equals方法),如果相同,那么就將該位置上的那個對象(Entry類型)的value值替換掉;否則,沿著該Entry的鏈繼續重復上述過程,如果到鏈的最后依然沒有找到與此對象相同的對象,那么這個時候就會將該對象增加到數組中,然后將數組中該位置上的那個對象鏈到這個新對象的后面。

 

7. 對于HashSet,HashMap來說,這樣做的原因就是為了提高查找的速度,使得查找時間不隨Set或者Map的大小而改變。

 本文由用戶 yanguz123 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!