hashCode之一--兩個對象值相同,有相同的hash code


兩個對象值相同(x.equals(y) == true),則一定有相同的hash code。

 

這是java語言的定義: 

因為:Hash,一般翻譯做“散列”,也有直接音譯為"哈希"的,就是把任意長度的輸入(又叫做預映射, pre-image),通過散列算法,變換成固定長度的輸出,該輸出就是散列值。這種轉換是一種壓縮映射,也就是,散列值的空間通常遠小於輸入的空間,不同的輸入可能會散列成相同的輸出,而不可能從散列值來唯一的確定輸入值。
1) 對象相等則hashCode一定相等;
2) hashCode相等對象未必相等。(不同對象的hashcode是否一定不一樣?是錯誤的,hashcode本身就是個函數,是可以重載的,你完全可以寫個函數總是返回固定值。但hashcode函數從設計要求上來說,要盡量保證:不同對象的hashcode不同。

這也涉及到如何寫自定義的hashCode方法的問題:必須符合以上條件。注意條件2中的未必。具體可參見java doc; Effective Java中有更詳細論述
本貼來自ZDNetChina中文社區 http://bbs.zdnet.com.cn ,本貼地址:http://bbs.zdnet.com.cn/viewthread.php?tid=362649

 

== 是比較地址是否相等,JAVA中聲明變量都是引用嘛,不同的引用,可能指向同一個地址。

equals 是比較值是否相等。

這種題很容易在面試中被問到。。。

 

hash code、equals和“==”三者的關系

 

1.如果是基本變量,沒有hashcode和equals方法,基本變量的比較方式就只有==,;

2.如果是變量,由於在java中所有變量定義都是一個指向實際存儲的一個句柄(你可以理解為c++中的指針),在這里==是比較句柄的地址(你可以理解為指針的存儲地址),而不是句柄指向的實際內存中的內容,如果要比較實際內存中的內容,那就要用equals方法,但是!!!

如果是你自己定義的一個類,比較自定義類用equals和==是一樣的,都是比較句柄地址,因為自定義的類是繼承於object,而object中的equals就是用==來實現的,你可以看源碼。

那為什么我們用的String等等類型equals是比較實際內容呢,是因為String等常用類已經重寫了object中的equals方法,讓equals來比較實際內容,你也可以看源碼。

3. hashcode
在一般的應用中你不需要了解hashcode的用法,但當你用到hashmap,hashset等集合類時要注意下hashcode

你想通過一個object的key來拿hashmap的value,hashmap的工作方法是,通過你傳入的object的hashcode在內存中找地址,當找到這個地址后再通過equals方法來比較這個地址中的內容是否和你原來放進去的一樣,一樣就取出value。

所以這里要匹配2部分,hashcode和equals
但假如說你new一個object作為key去拿value是永遠得不到結果的,因為每次new一個object,這個object的hashcode是永遠不同的,所以我們要重寫hashcode,你可以令你的hashcode是object中的一個恆量,這樣永遠可以通過你的object的hashcode來找到key的地址,然后你要重寫你的equals方法,使內存中的內容也相等。。。

 

 

首先,從語法角度,也就是從強制性的角度來說,hashCode和equals是兩個獨立的,互不隸屬,互不依賴的方法,equals成立與hashCode相等這兩個命題之間,誰也不是誰的充分條件或者必要條件。  
   
  但是,從為了讓我們的程序正常運行的角度,我們應當向Effective   Java中所言  
   
  重載equals的時候,一定要(正確)重載hashCode  
   
  使得equals成立的時候,hashCode相等,也就是a.equals(b)->a.hashCode()   ==   b.hashCode(),或者說此時,equals是hashCode相等的充分條件,hashCode相等是equals的必要條件(從數學課上我們知道它的逆否命題:hashCode不相等也不會equals),但是它的逆命題,hashCode相等一定equals以及否命題不equals時hashCode不等都不成立。  
   
  所以,如果面試的時候,最好把hashCode與equals之間沒有強制關系,以及根據(沒有語法約束力的)規范的角度,應當做到...這兩層意思都說出來:P  

 

 

  總結一下,equals()是對象相等性比較,hashCode()是計算對象的散列值,當然他們的依據是對象的屬性。

 對於equals,一般我們認為兩個對象同類型並且所有屬性相等的時候才是相等的,在類中必須改寫equals,因為Object類中的equals只是判斷兩個引用變量是否引用同一對象,如果不是引用同一對象,即使兩個對象的內容完全相同,也會返回false。當然,在類中改寫這個equals時,你也可以只對部分屬性進行比較,只要這些屬性相同就認為對象是相等的。  
   
  對於hashCode,只要是用在和哈希運算有關的地方,前面很多兄弟都提到了,和equals一樣,在你的類中也應該改寫。當然如果兩個對象是完全相同的,那么他們的hashCode當然也是一樣的,但是象前面所述,規則可以由你自己來定義,因此兩者之間並沒有什么必然的聯系。  
   
  當然,大多數情況下我們還是根據所有的屬性來計算hashCode和進行相等性比較。


免責聲明!

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



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