JDK 是如何判斷兩個(gè)對(duì)象是否相同的呢?判斷的流程是什么?
參考解答:
JDK 會(huì)先判斷兩個(gè)對(duì)象的hashCode是否相同,如果hashCode不同,則說(shuō)明肯定是兩個(gè)不同的對(duì)象了;如果hashCode相同再通過(guò)equals()方法進(jìn)行進(jìn)一步比較,如果equals方法返回true,則說(shuō)明兩個(gè)對(duì)象是相同的,如果equals方法返回false說(shuō)明兩個(gè)對(duì)象不同。
怎么來(lái)驗(yàn)證這個(gè)問(wèn)題呢?我們知道HashSet是不允許存儲(chǔ)相同的鍵值的。所以我們可以用HashSet存儲(chǔ)兩個(gè)相同的鍵值來(lái)模擬,看JDK是如何做判斷和識(shí)別的,從而驗(yàn)證我們的猜想。
// 先自定義一個(gè)類(lèi)并復(fù)寫(xiě) hashCode 和 equals 方法 public class CustomClass { @Override public int hashCode() { System.out.println("判斷 hashCode"); return 1; // 返回1,說(shuō)明所有新建的對(duì)象的哈希值都為1,也就是相同 } @Override public boolean equals(Object o) { System.out.println("判斷 equals"); return true; // 返回true } }
接下來(lái)我們用HashSet來(lái)存儲(chǔ)兩個(gè)自定義的CustomClass的對(duì)象,代碼如下:
public class HashSetTest { public static void main(String[] args) { HashSeths = new HashSet<>(); CustomClass cs1 = new CustomClass(); CustomClass cs2 = new CustomClass(); hs.add(cs1); hs.add(cs2); System.out.println("----hs添加完畢"); System.out.println("hs:"+hs); // 打印一下hashSet集合看里面存放了什么 } }
打印結(jié)果如下:
判斷 hashCode 判斷 hashCode 判斷 equals ----hs添加完畢 判斷 hashCode // 此處的判斷是打印輸出語(yǔ)句執(zhí)行時(shí)調(diào)用的,與分析本問(wèn)題無(wú)關(guān) hs:[com.alankeene.javalib.collections.CustomClass@1]
結(jié)果分析:
執(zhí)行 hs.add(cs1) 語(yǔ)句的時(shí)候,JDK 會(huì)先判斷 cs1 所指向?qū)ο蟮膆ashCode,因?yàn)槭堑谝淮瓮鵋ashSet集合里面存放元素,該元素 hashCode 在集合中肯定是還沒(méi)存在的,這是個(gè)新的元素,所以直接存放進(jìn)集合中,不用調(diào)用 cs1 所指向?qū)ο蟮?equals 方法。
當(dāng)執(zhí)行 hs.add(cs2) 語(yǔ)句時(shí),這是第二次往集合里存放元素,有新的元素 cs2 要添加進(jìn)來(lái),那先要調(diào)用 cs2 所指向?qū)ο蟮?hashCode 方法看看它的哈希值是不是與集合中已有元素的哈希值重復(fù)了,發(fā)現(xiàn)重復(fù)了,哈希值都是1,那有可能是同一個(gè)對(duì)象,那就要調(diào)用 cs2 所指向?qū)ο蟮?equals 方法做進(jìn)一步判斷,發(fā)現(xiàn) equals 方法返回 true,則判斷為是重復(fù)的元素,就不往集合里添加了。
所以最終打印 HashSet 集合的時(shí)候可以看到,集合中只存放了一個(gè)元素。
注:所以平時(shí)我們?cè)谧远x一個(gè)類(lèi)時(shí),要謹(jǐn)慎把 equals 方法的返回值靜態(tài)的設(shè)置為 true,因?yàn)橐坏┊a(chǎn)生哈希沖突,JDK 就會(huì)認(rèn)為相同哈希值的對(duì)象就是同一個(gè)對(duì)象了。
我們?cè)俜醋C一下,把 equals 方法改為返回 false,模擬兩個(gè)hashCode相同,但是是兩個(gè)不同的對(duì)象的情景。
public class CustomClass { @Override public int hashCode() { System.out.println("判斷 hashCode"); return 1; // 返回1,說(shuō)明所有新建的對(duì)象的哈希值都為1,也就是相同 } @Override public boolean equals(Object o) { System.out.println("判斷 equals"); return false; // 返回false } }
打印結(jié)果會(huì)如下:
判斷 hashCode 判斷 hashCode 判斷 equals ----hs添加完畢 判斷 hashCode // 此處的判斷是打印輸出語(yǔ)句執(zhí)行時(shí)調(diào)用的,與分析本問(wèn)題無(wú)關(guān) 判斷 hashCode // 此處的判斷是打印輸出語(yǔ)句執(zhí)行時(shí)調(diào)用的,與分析本問(wèn)題無(wú)關(guān) hs:[com.alankeene.javalib.collections.CustomClass@1, com.alankeene.javalib.collections.CustomClass@1]
會(huì)發(fā)現(xiàn),HashSet集合中存放了兩個(gè)元素了,說(shuō)明雖然 cs1 和 cs2 的哈希值相同,但是 JDK 判斷為不同的元素并存入集合中了。
由此,驗(yàn)證了我們的猜想。JDK 是先判斷 hashCode,如果 hashCode 相同再通過(guò) equals 去判斷兩個(gè)對(duì)象是否相同的。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/73383.html
摘要:注實(shí)際應(yīng)用中,我們一般是用集合來(lái)存儲(chǔ)相同的字符串的,不會(huì)用來(lái)存。解答雖然我們不能用來(lái)存放類(lèi)型重復(fù)的字符串,但我們可以用來(lái)存儲(chǔ)類(lèi)型重復(fù)的字符串呀。而對(duì)于類(lèi)型,相同字符串的不同對(duì)象哈希值是不同的。 有一種學(xué)得快的方法,就是不要一次學(xué)太多。 1. 前言 今天,我們來(lái)探討一個(gè)實(shí)際中不常用但卻比較有意思的問(wèn)題。它能幫助你理解 HashSet中的鍵值是唯一的,不可重復(fù)的 這句話的真正含義,也考驗(yàn)?zāi)?..
摘要:發(fā)生了線程不安全情況。本來(lái)在中,發(fā)生哈希沖突是可以用鏈表法或者紅黑樹(shù)來(lái)解決的,但是在多線程中,可能就直接給覆蓋了。中,當(dāng)同一個(gè)值上元素的鏈表節(jié)點(diǎn)數(shù)不小于時(shí),將不再以單鏈表的形式存儲(chǔ)了,會(huì)被調(diào)整成一顆紅黑樹(shù)。 showImg(https://segmentfault.com/img/bVbsVLk?w=288&h=226); List 和 Set 的區(qū)別 List , Set 都是繼承自...
摘要:如果沒(méi)有,那必須先執(zhí)行相應(yīng)的類(lèi)加載過(guò)程。分配內(nèi)存在類(lèi)加載檢查通過(guò)后,接下來(lái)虛擬機(jī)將為新生對(duì)象分配內(nèi)存。程序計(jì)數(shù)器主要有兩個(gè)作用字節(jié)碼解釋器通過(guò)改變程序計(jì)數(shù)器來(lái)依次讀取指令,從而實(shí)現(xiàn)代碼的流程控制,如順序執(zhí)行選擇循環(huán)異常處理。 目錄介紹 01.Java對(duì)象的創(chuàng)建過(guò)程 1.0 看下創(chuàng)建類(lèi)加載過(guò)程 1.1 對(duì)象的創(chuàng)建 1.2 對(duì)象的內(nèi)存布局 02.Java內(nèi)存區(qū)域 2.0 運(yùn)行...
摘要:最近經(jīng)過(guò)某大佬的建議準(zhǔn)備閱讀一下的源碼來(lái)提升一下自己所以開(kāi)始寫(xiě)源碼分析的文章閱讀版本為目錄結(jié)構(gòu)圖構(gòu)造器方法方法方法方法方法方法結(jié)構(gòu)圖類(lèi)構(gòu)造器類(lèi)構(gòu)造器是創(chuàng)建對(duì)象的方法之一。還有一種情況是兩個(gè)元素不相同,但是相同,這就是哈希碰撞。 最近經(jīng)過(guò)某大佬的建議準(zhǔn)備閱讀一下JDK的源碼來(lái)提升一下自己 所以開(kāi)始寫(xiě)JDK源碼分析的文章 閱讀JDK版本為1.8 目錄 Object結(jié)構(gòu)圖 構(gòu)造器 eq...
摘要:如果對(duì)象長(zhǎng)度不相等,則為假。從后往前,判斷類(lèi)中數(shù)組的單個(gè)字符是否相等,有不相等則為假。由此可以看出,如果對(duì)兩個(gè)超長(zhǎng)的字符串進(jìn)行比較還是非常費(fèi)時(shí)間的。字符串?dāng)?shù)值化比較將字符串?dāng)?shù)值化。 引言 從一段代碼說(shuō)起: public void stringTest(){ String a = a+b+1; String b = ab1; System.out.println(...
閱讀 2311·2021-11-17 09:33
閱讀 2845·2021-11-12 10:36
閱讀 3481·2021-09-27 13:47
閱讀 965·2021-09-22 15:10
閱讀 3565·2021-09-09 11:51
閱讀 1492·2021-08-25 09:38
閱讀 2813·2019-08-30 15:55
閱讀 2668·2019-08-30 15:53