Java重写equals方法时为什么要重写hashCode方法
在我們平時編寫Java代碼時,重寫equals方法時一定要重寫hashCode方法,這是為什么呢?
在討論這個問題前,我們先看下Object類中hashCode方法和equals方法。
hashCode方法:
翻譯如下:
equals方法:
翻譯如下:
1、hashCode方法的作用
在Java中也一樣,hashCode方法的主要作用是為了配合基于散列的集合一起正常運行,這樣的散列集合包括HashSet、HashMap以及HashTable。
為什么這么說呢?考慮一種情況,當(dāng)向集合中插入對象時,如何判別在集合中是否已經(jīng)存在該對象了?
也許大多數(shù)人都會想到調(diào)用equals方法來逐個進行比較,這個方法確實可行。但是如果集合中已經(jīng)存在一萬條數(shù)據(jù)或者更多的數(shù)據(jù),如果采用equals方法去逐一比較,效率必然是一個問題。
此時hashCode方法的作用就體現(xiàn)出來了,當(dāng)集合要添加新的對象時,先調(diào)用這個對象的hashCode方法,得到對應(yīng)的hashcode值,實際上在HashMap的具體實現(xiàn)中會用一個table保存已經(jīng)存進去的對象的hashcode值,如果table中沒有該hashcode值,它就可以直接存進去,不用再進行任何比較了;如果存在該hashcode值, 就調(diào)用它的equals方法與新元素進行比較,相同的話就不存了,不相同就散列其它的地址,所以這里存在一個沖突解決的問題,這樣一來實際調(diào)用equals方法的次數(shù)就大大降低了,說通俗一點:Java中的hashCode方法就是根據(jù)一定的規(guī)則將與對象相關(guān)的信息(比如對象的存儲地址,對象的字段等)映射成一個數(shù)值,這個數(shù)值稱作為散列值。
java.util.HashMap的中put方法的具體實現(xiàn),先計算key的hash值,從table數(shù)組中取出對應(yīng)節(jié)點,如果節(jié)點不存在則添加一個節(jié)點;如果存在則更新value,返回舊value。
hash方法會調(diào)用對象的hashCode()方法:
addEntry方法添加新節(jié)點:
new一個Entry實例,next指向原有的Entry實例。也就是新new的Entry實例是該鏈表的頭。
Entry是一個靜態(tài)內(nèi)部類,有一個屬性next,指向下一個Entry,形成一個鏈表結(jié)構(gòu)。
2、equals方法和hashCode方法
看下面代碼:
輸出結(jié)果:
我們Student類重寫了equals方法,hashCode方法沒有重寫,s1和s2的姓名和年齡相同,equals方法為true,認為是同一個人。但是s1和s2的hashCode返回不同。
我們看下hashMap的get方法,先獲取key的hashCode,由于s1和s2的hashCode不同,所以hashMap.get(s2)得到的是null。
接下來我們重寫下Student類的hashCode方法,讓equals方法和hashCode方法始終在邏輯上保持一致性。
重新運行,輸出結(jié)果如下,s1和s2的hashCode相同了,hashMap.get(s2)得到了1。
① 在 Java 應(yīng)用程序執(zhí)行期間,在對同一對象多次調(diào)用 hashCode 方法時,必須一致地返回相同的整數(shù),前提是將對象進行 equals 比較時所用的信息沒有被修改。從某一應(yīng)用程序的一次執(zhí)行到同一應(yīng)用程序的另一次執(zhí)行,該整數(shù)無需保持一致。
② 如果根據(jù) equals(Object) 方法,兩個對象是相等的,那么對這兩個對象中的每個對象調(diào)用 hashCode 方法都必須生成相同的整數(shù)結(jié)果。
③ 如果根據(jù) equals(java.lang.Object) 方法,兩個對象不相等,那么對這兩個對象中的任一對象上調(diào)用 hashCode 方法不 要求一定生成不同的整數(shù)結(jié)果。但是,程序員應(yīng)該意識到,為不相等的對象生成不同整數(shù)結(jié)果可以提高哈希表的性能。
如果hashCode方法依賴于對象中易變的數(shù)據(jù),用戶就要當(dāng)心了,因為此數(shù)據(jù)發(fā)生變化時,hashCode()方法就會生成一個不同的hash值。看下面例子:
修改了age屬性的值,導(dǎo)致hashCode變化,所以輸出為“null”。
因此,在設(shè)計hashCode方法和equals方法的時候,如果對象中的數(shù)據(jù)易變,則最好在equals方法和hashCode方法中不要依賴于該字段。
總結(jié)
以上是生活随笔為你收集整理的Java重写equals方法时为什么要重写hashCode方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 共建智慧海关 第四范式打造快、准、稳海关
- 下一篇: 蝉联IDC机器学习平台市场No.1 第