兩個對象值相同(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和進行相等性比較。