重新實(shí)現(xiàn)hashCode()方法
在Java中,為了讓對(duì)象在集合中能夠更高效地進(jìn)行查找和比較,我們通常需要重寫對(duì)象的equals()
和hashCode()
方法。其中,equals()
方法用于比較兩個(gè)對(duì)象是否相等,而hashCode()
方法則用于返回對(duì)象哈希值,供集合類使用。
默認(rèn)情況下,Java會(huì)根據(jù)每個(gè)對(duì)象的內(nèi)存地址來計(jì)算哈希值,因此如果兩個(gè)對(duì)象在內(nèi)存中的位置不同,它們的哈希值也會(huì)不同。但是,在實(shí)際開發(fā)中,我們可能需要比較的是對(duì)象的屬性值而不是內(nèi)存地址,這時(shí)就需要自己來實(shí)現(xiàn)hashCode()
方法了。
為什么需要重新實(shí)現(xiàn)hashCode()方法
雖然默認(rèn)實(shí)現(xiàn)的hashCode()
方法可以滿足基本的哈希表需求,但是它有一個(gè)很大的問題:它只是返回對(duì)象的內(nèi)存地址的哈希碼,這意味著兩個(gè)內(nèi)容完全相同的對(duì)象在哈希表中還是會(huì)被認(rèn)為是不同的對(duì)象,這樣就會(huì)浪費(fèi)大量的空間和時(shí)間。例如:
String s1 = new String("hello"); String s2 = new String("hello"); System.out.println(s1.hashCode()); // 輸出 99162322 System.out.println(s2.hashCode()); // 輸出 99162322
雖然s1
和s2
的內(nèi)容相同,但是它們?cè)趦?nèi)存中的地址不同,因此它們的哈希值也不同。
在實(shí)際使用中,這可能會(huì)導(dǎo)致一些問題,比如無法正確識(shí)別集合中的重復(fù)元素。
但是一些標(biāo)準(zhǔn)Java類庫中的類(例如String
、Integer
等)已經(jīng)重寫了hashCode()
方法,以便讓具有相同屬性值的對(duì)象具有相同的哈希碼。
所以上面代碼結(jié)果會(huì)顯示哈希值相同。
如何重新實(shí)現(xiàn)hashCode()方法
要重新實(shí)現(xiàn)hashCode()
方法,我們需要結(jié)合對(duì)象的屬性值來計(jì)算哈希碼,以便讓具有相同屬性值的對(duì)象具有相同的哈希碼。一般來說,可以采用以下步驟:
把對(duì)象的非零屬性用一個(gè)質(zhì)數(shù)(比如31)進(jìn)行加權(quán),并把它們相加。 如果屬性是布爾型,則使用(f ? 1 : 0)
的形式轉(zhuǎn)換成數(shù)值型。 如果屬性是浮點(diǎn)型,則使用Float.floatToIntBits(f)
的方式把它們轉(zhuǎn)換成整型。 如果屬性是雙精度型,則使用Double.doubleToLongBits(f)
的方式把它們轉(zhuǎn)換成長(zhǎng)整型,并對(duì)其進(jìn)行異或操作。 如果屬性是數(shù)組,則對(duì)每個(gè)元素進(jìn)行遞歸處理。
例如,在一個(gè)自定義的Person
類中,如果我們想讓兩個(gè)對(duì)象在name
和age
屬性都相同的情況下返回相同的哈希碼,可以按照以下方式重新實(shí)現(xiàn)hashCode()
方法:
@Override public int hashCode() { int result = 17; result = 31 * result + name.hashCode(); result = 31 * result + age; return result; }
其中,17
和31
都是選定的質(zhì)數(shù)。
注意事項(xiàng)
在重新實(shí)現(xiàn)hashCode()
方法時(shí),需要牢記以下幾點(diǎn):
哈希碼的計(jì)算方式應(yīng)該盡量均勻分布,這樣可以提高哈希表的性能。 如果兩個(gè)對(duì)象的equals()
方法返回true
,那么它們的哈希碼應(yīng)該相同。 如果對(duì)象的屬性值發(fā)生變化,那么它的哈希碼也應(yīng)該隨之變化。 哈希碼的計(jì)算過程中,應(yīng)該避免使用可能會(huì)發(fā)生溢出的操作。 建議使用自動(dòng)生成的hashCode()
方法,例如Eclipse和IntelliJ IDEA都支持自動(dòng)生成hashCode()
和equals()
方法的功能。 總結(jié)
重新實(shí)現(xiàn)hashCode()
方法可以提高哈希表的效率,使得具有相同屬性值的對(duì)象具有相同的哈希碼。要實(shí)現(xiàn)hashCode()
方法,需要按照一定的步驟進(jìn)行計(jì)算,并考慮到一些細(xì)節(jié)問題。在實(shí)際開發(fā)中,建議使用自動(dòng)生成的hashCode()
方法。
hashCode()方法是Java中的一個(gè)重要方法,用于計(jì)算對(duì)象的哈希碼。重新實(shí)現(xiàn)hashCode()方法可以根據(jù)具體的業(yè)務(wù)需求來選擇不同的計(jì)算方法,從而提高哈希表的效率。在實(shí)現(xiàn)過程中,需要注意避免哈希沖突,可以使用開放地址法、鏈地址法等方法來解決。此外,還可以使用一些優(yōu)化技巧,如緩存哈希碼、使用位運(yùn)算等方法來提高計(jì)算效率。總之,重新實(shí)現(xiàn)hashCode()方法是Java開發(fā)中的一個(gè)重要技能,可以幫助我們更好地理解哈希表的原理和應(yīng)用。
到此這篇關(guān)于重新實(shí)現(xiàn)hashCode()方法的文章就介紹到這了,更多相關(guān)重新實(shí)現(xiàn)hashCode()內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- java中hashCode方法與equals方法的用法總結(jié)
- 詳解hashCode()和equals()的本質(zhì)區(qū)別和聯(lián)系
- 重寫hashCode()和equals()方法詳細(xì)介紹
- JAVA hashCode使用方法詳解
- 詳解Java中用于查找對(duì)象哈希碼值的hashCode()函數(shù)
- 為什么在重寫 equals方法的同時(shí)必須重寫 hashcode方法
- java 中HashCode重復(fù)的可能性
- why在重寫equals時(shí)還必須重寫hashcode方法分享
- javascript中實(shí)現(xiàn)兼容JAVA的hashCode算法代碼分享
相關(guān)文章
實(shí)例分析Java Class的文件結(jié)構(gòu)
今天把之前在Evernote中的筆記重新整理了一下,發(fā)上來供對(duì)java class 文件結(jié)構(gòu)的有興趣的同學(xué)參考一下2013-04-04Spring的Xml和JavaConfig 擴(kuò)展哪個(gè)好用
今天給大家介紹基于注解的Spring擴(kuò)展,Spring的Xml和JavaConfig 擴(kuò)展的配置方法,關(guān)于Spring的Xml和JavaConfig 擴(kuò)展你會(huì)選哪個(gè)呢,帶著這個(gè)問題一起通過本文學(xué)習(xí)下吧2021-05-05Java設(shè)計(jì)模式之Builder建造者模式
這篇文章主要為大家詳細(xì)介紹了Java設(shè)計(jì)模式之Builder建造者模式的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03深入解析Java的Struts框架中的控制器DispatchAction
這篇文章主要介紹了深入解析Java的Struts框架中的控制器DispatchAction,Struts是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下2015-12-12單機(jī)redis分布式鎖實(shí)現(xiàn)原理解析
這篇文章主要介紹了單機(jī)redis分布式鎖實(shí)現(xiàn)原理解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04Java基礎(chǔ)學(xué)習(xí)之字符緩沖流的應(yīng)用
這篇文章主要為大家詳細(xì)介紹了Java基礎(chǔ)中的字符緩沖流的相關(guān)應(yīng)用,例如復(fù)制Java文件等,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一2022-09-09基于hibernate實(shí)現(xiàn)的分頁技術(shù)實(shí)例分析
這篇文章主要介紹了基于hibernate實(shí)現(xiàn)的分頁技術(shù),結(jié)合實(shí)例形式分析了Hibernate分頁技術(shù)的原理,實(shí)現(xiàn)步驟與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2016-03-03Java+MySql圖片數(shù)據(jù)保存與讀取的具體實(shí)例
之前一直沒有做過涉及到圖片存儲(chǔ)的應(yīng)用,最近要做的東東涉及到了這個(gè)點(diǎn),就做了一個(gè)小的例子算是對(duì)圖片存儲(chǔ)的初試吧2013-06-06