為什么要重寫hashcode() 方法


Java中的集合(Collection)有兩類,一類是List,再有一類是Set。 
前者集合內的元素是有序的,元素可以重復;后者元素無序,但元素不可重復。 
那么我們怎么判斷兩個元素是否重復呢? 這就是Object.equals方法了。

通常想查找一個集合中是否包含某個對象,就是逐一取出每個元素與要查找的元素進行比較,當發現某個元素與要查找的對象進行equals方法比較的結果相等時,則停止繼續查找並返回肯定的信息,否則返回否定的信息,如果一個集合中有很多元素譬如成千上萬的元素,並且沒有包含要查找的對象時,則意味着你的程序需要從該集合中取出成千上萬個元素進行逐一比較才能得到結論,於是,有人就發明了一種哈希算法來提高從集合中查找元素的效率,這種方式將集合分成若干個存儲區域,每個對象可以計算出一個哈希碼,可以將哈希碼分組,每組分別對應某個存儲區域,根據一個對象的哈希碼就可以確定該對象應該存儲的那個區域.

hashCode方法可以這樣理解:它返回的就是根據對象的內存地址換算出的一個值。這樣一來,當集合要添加新的元素時,先調用這個元素的hashCode方法,就一下子能定位到它應該放置的物理位置上。如果這個位置上沒有元素,它就可以直接存儲在這個位置上,不用再進行任何比較了;如果這個位置上已經有元素了,就調用它的equals方法與新元素進行比較,相同的話就不存了,不相同就散列其它的地址。這樣一來實際調用equals方法的次數就大大降低了,幾乎只需要一兩次。

談到hashcode()和equals()就不能不說到hashset,hashmap,hashtable中的使用,具體是怎樣呢,請看如下分析:

Hashset是繼承Set接口,Set接口又實現Collection接口,這是層次關系。那么hashset是根據什么原理來存取對象的呢? 
在hashset中不允許出現重復對象,元素的位置也是不確定的。在hashset中又是怎樣判定元素是否重復的呢?判斷兩個對象是否相等的規則是: 
.1),判斷兩個對象的hashCode是否相等 
如果不相等,認為兩個對象也不相等,完畢,如果相等,轉入2
.2),判斷兩個對象用equals運算是否相等 
如果不相等,認為兩個對象也不相等 
如果相等,認為兩個對象相等(equals()是判斷兩個對象是否相等的關鍵) 

小結:
(1)只有類的實例對象要被采用哈希算法進行存儲和檢索時,這個類才需要按要求覆蓋hashCode方法,即使程序可能暫時不會用到當前類的hashCode方法,但是為它提供一個hashCode方法也不會有什么不好,沒准以后什么時候又用到這個方法了,所以,通常要求hashCode方法和equals方法一並被同時覆蓋。

(2)equals()相等的兩個對象,hashcode()一定相等;equals()不相等的兩個對象,卻並不能證明他們的hashcode()不相等。換句話說,equals()方法不相等的兩個對象,hashcode()有可能相等。反過來:hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。

提示:
(1)通常來說,一個類的兩個實例對象用equal方法比較的結果相等時,它們的哈希碼也必須相等,但反之則不成立,即equals方法比較結果不相等的對象可以有相同的哈希碼,或者說哈希碼相同的兩個對象的equal方法比較的結果可以不等。

(2)當一個對象被存儲進hashset集合中以后,就不能修改這個對象中的那些參與計算哈希值的字段了,否則,對象修改后的哈希值與最初存儲進hashset集合時的哈希值就不同了,這種情況下,即使在contains方法使用該對象的當前引用作為的參數去hashset集合中檢索對象,也將返回找不到對象的結果,這也會導致無法從hashset集合中單獨刪除當前對象,從而造成內存泄露,所謂的內存泄露也就說有一個對象不再被使用,但它一直占有內存空間,沒有被釋放。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM