一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - Java教程 - java中hashCode方法與equals方法的用法總結(jié)

java中hashCode方法與equals方法的用法總結(jié)

2019-10-16 10:30java之家 Java教程

總的來(lái)說(shuō),Java中的集合(Collection)有兩類,一類是List,再有一類是Set。前者集合內(nèi)的元素是有序的,元素可以重復(fù);后者元素?zé)o序,但元素不可重復(fù)

首先,想要明白hashCode的作用,必須要先知道Java中的集合?! ?/p>

總的來(lái)說(shuō),Java中的集合(Collection)有兩類,一類是List,再有一類是Set。 前者集合內(nèi)的元素是有序的,元素可以重復(fù);后者元素?zé)o序,但元素不可重復(fù)。

那么這里就有一個(gè)比較嚴(yán)重的問(wèn)題了:要想保證元素不重復(fù),可兩個(gè)元素是否重復(fù)應(yīng)該依據(jù)什么來(lái)判斷呢? 這就是Object.equals方法了。但是,如果每增加一個(gè)元素就檢查一次,那么當(dāng)元素很多時(shí),后添加到集合中的元素比較的次數(shù)就非常多了。 也就是說(shuō),如果集合中現(xiàn)在已經(jīng)有1000個(gè)元素,那么第1001個(gè)元素加入集合時(shí),它就要調(diào)用1000次equals方法。這顯然會(huì)大大降低效率。  

于是,Java采用了哈希表的原理。哈希(Hash)實(shí)際上是個(gè)人名,由于他提出一哈希算法的概念,所以就以他的名字命名了。 哈希算法也稱為散列算法,是將數(shù)據(jù)依特定算法直接指定到一個(gè)地址上。初學(xué)者可以這樣理解,hashCode方法實(shí)際上返回的就是對(duì)象存儲(chǔ)的物理地址(實(shí)際可能并不是)。   

這樣一來(lái),當(dāng)集合要添加新的元素時(shí),先調(diào)用這個(gè)元素的hashCode方法,就一下子能定位到它應(yīng)該放置的物理位置上。 如果這個(gè)位置上沒有元素,它就可以直接存儲(chǔ)在這個(gè)位置上,不用再進(jìn)行任何比較了;如果這個(gè)位置上已經(jīng)有元素了, 就調(diào)用它的equals方法與新元素進(jìn)行比較,相同的話就不存了,不相同就散列其它的地址。 所以這里存在一個(gè)沖突解決的問(wèn)題。這樣一來(lái)實(shí)際調(diào)用equals方法的次數(shù)就大大降低了,幾乎只需要一兩次。 

所以,Java對(duì)于eqauls方法和hashCode方法是這樣規(guī)定的:

1、如果兩個(gè)對(duì)象相同,那么它們的hashCode值一定要相同;

2、如果兩個(gè)對(duì)象的hashCode相同,它們并不一定相同(上面說(shuō)的對(duì)象相同指的是用eqauls方法比較。)  

你當(dāng)然可以不按要求去做了,但你會(huì)發(fā)現(xiàn),相同的對(duì)象可以出現(xiàn)在Set集合中。同時(shí),增加新元素的效率會(huì)大大下降。

hashcode這個(gè)方法是用來(lái)鑒定2個(gè)對(duì)象是否相等的。 那你會(huì)說(shuō),不是還有equals這個(gè)方法嗎? 不錯(cuò),這2個(gè)方法都是用來(lái)判斷2個(gè)對(duì)象是否相等的。但是他們是有區(qū)別的。 一般來(lái)講,equals這個(gè)方法是給用戶調(diào)用的,如果你想判斷2個(gè)對(duì)象是否相等,你可以重寫equals方法,然后在代碼中調(diào)用,就可以判斷他們是否相等 了。簡(jiǎn)單來(lái)講,equals方法主要是用來(lái)判斷從表面上看或者從內(nèi)容上看,2個(gè)對(duì)象是不是相等。

舉個(gè)例子,有個(gè)學(xué)生類,屬性只有姓名和性別,那么我們可以 認(rèn)為只要姓名和性別相等,那么就說(shuō)這2個(gè)對(duì)象是相等的。 hashcode方法一般用戶不會(huì)去調(diào)用,比如在hashmap中,由于key是不可以重復(fù)的,他在判斷key是不是重復(fù)的時(shí)候就判斷了hashcode 這個(gè)方法,而且也用到了equals方法。這里不可以重復(fù)是說(shuō)equals和hashcode只要有一個(gè)不等就可以了!所以簡(jiǎn)單來(lái)講,hashcode相 當(dāng)于是一個(gè)對(duì)象的編碼,就好像文件中的md5,他和equals不同就在于他返回的是int型的,比較起來(lái)不直觀。我們一般在覆蓋equals的同時(shí)也要 覆蓋hashcode,讓他們的邏輯一致。舉個(gè)例子,還是剛剛的例子,如果姓名和性別相等就算2個(gè)對(duì)象相等的話,那么hashcode的方法也要返回姓名 的hashcode值加上性別的hashcode值,這樣從邏輯上,他們就一致了。 要從物理上判斷2個(gè)對(duì)象是否相等,用==就可以了。

在Java語(yǔ)言中,equals()和hashCode()兩個(gè)函數(shù)的使用是緊密配合的,你要是自己設(shè)計(jì)其中一個(gè),就要設(shè)計(jì)另外一個(gè)。在多數(shù)情況 下,這兩個(gè)函數(shù)是不用考慮的,直接使用它們的默認(rèn)設(shè)計(jì)就可以了。但是在一些情況下,這兩個(gè)函數(shù)最好是自己設(shè)計(jì),才能確保整個(gè)程序的正常運(yùn)行。最常見的是當(dāng) 一個(gè)對(duì)象被加入收集對(duì)象(collection object)時(shí),這兩個(gè)函數(shù)必須自己設(shè)計(jì)。更細(xì)化的定義是:如果你想將一個(gè)對(duì)象A放入另一個(gè)收集對(duì)象B里,或者使用這個(gè)對(duì)象A為查找一個(gè)元對(duì)象在收集對(duì) 象B里位置的鑰匙,并支持是否容納,刪除收集對(duì)象B里的元對(duì)象這樣的操作,那么,equals()和hashCode()函數(shù)必須開發(fā)者自己定義。其他情 況下,這兩個(gè)函數(shù)是不需要定義的。

equals():

它是用于進(jìn)行兩個(gè)對(duì)象的比較的,是對(duì)象內(nèi)容的比較,當(dāng)然也能用于進(jìn)行對(duì)象參閱值的比較。什么是對(duì)象參閱值的比較?就是兩個(gè)參閱變量的值得比較,我們 都知道參閱變量的值其實(shí)就是一個(gè)數(shù)字,這個(gè)數(shù)字可以看成是鑒別不同對(duì)象的代號(hào)。兩個(gè)對(duì)象參閱值的比較,就是兩個(gè)數(shù)字的比較,兩個(gè)代號(hào)的比較。這種比較是默 認(rèn)的對(duì)象比較方式,在Object這個(gè)對(duì)象中,這種方式就已經(jīng)設(shè)計(jì)好了。所以你也不用自己來(lái)重寫,浪費(fèi)不必要的時(shí)間。

對(duì)象內(nèi)容的比較才是設(shè)計(jì)equals()的真正目的,Java語(yǔ)言對(duì)equals()的要求如下,這些要求是必須遵循的。否則,你就不該浪費(fèi)時(shí)間:

•對(duì)稱性:如果x.equals(y)返回是“true”,那么y.equals(x)也應(yīng)該返回是“true”。

•反射性:x.equals(x)必須返回是“true”。

•類推性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也應(yīng)該返回是“true”。

•還有一致性:如果x.equals(y)返回是“true”,只要x和y內(nèi)容一直不變,不管你重復(fù)x.equals(y)多少次,返回都是“true”。

•任何情況下,x.equals(null),永遠(yuǎn)返回是“false”;x.equals(和x不同類型的對(duì)象)永遠(yuǎn)返回是“false”。

hashCode():
這個(gè)函數(shù)返回的就是一個(gè)用來(lái)進(jìn)行赫希操作的整型代號(hào),請(qǐng)不要把這個(gè)代號(hào)和前面所說(shuō)的參閱變量所代表的代號(hào)弄混了。后者不僅僅是個(gè)代號(hào)還具有在內(nèi)存中才查找對(duì) 象的位置的功能。hashCode()所返回的值是用來(lái)分類對(duì)象在一些特定的收集對(duì)象中的位置。這些對(duì)象是HashMap, Hashtable, HashSet,等等。這個(gè)函數(shù)和上面的equals()函數(shù)必須自己設(shè)計(jì),用來(lái)協(xié)助HashMap, Hashtable, HashSet,等等對(duì)自己所收集的大量對(duì)象進(jìn)行搜尋和定位。

這些收集對(duì)象究竟如何工作的,想象每個(gè)元對(duì)象hashCode是一個(gè)箱子的 編碼,按照編碼,每個(gè)元對(duì)象就是根據(jù)hashCode()提供的代號(hào)歸入相應(yīng)的箱子里。所有的箱子加起來(lái)就是一個(gè)HashSet,HashMap,或 Hashtable對(duì)象,我們需要尋找一個(gè)元對(duì)象時(shí),先看它的代碼,就是hashCode()返回的整型值,這樣我們找到它所在的箱子,然后在箱子里,每 個(gè)元對(duì)象都拿出來(lái)一個(gè)個(gè)和我們要找的對(duì)象進(jìn)行對(duì)比,如果兩個(gè)對(duì)象的內(nèi)容相等,我們的搜尋也就結(jié)束。這種操作需要兩個(gè)重要的信息,一是對(duì)象的 hashCode(),還有一個(gè)是對(duì)象內(nèi)容對(duì)比的結(jié)果。

hashCode()的返回值和equals()的關(guān)系如下:

•如果x.equals(y)返回“true”,那么x和y的hashCode()必須相等。

•如果x.equals(y)返回“false”,那么x和y的hashCode()有可能相等,也有可能不等。

為什么這兩個(gè)規(guī)則是這樣的,原因其實(shí)很簡(jiǎn)單,拿HashSet來(lái)說(shuō)吧,HashSet可以擁有一個(gè)或更多的箱子,在同一個(gè)箱子中可以有一個(gè) 或更多的獨(dú)特元對(duì)象(HashSet所容納的必須是獨(dú)特的元對(duì)象)。這個(gè)例子說(shuō)明一個(gè)元對(duì)象可以和其他不同的元對(duì)象擁有相同的hashCode。但是一個(gè) 元對(duì)象只能和擁有同樣內(nèi)容的元對(duì)象相等。所以這兩個(gè)規(guī)則必須成立。

設(shè)計(jì)這兩個(gè)函數(shù)所要注意到的:
如果你設(shè)計(jì)的對(duì)象類型并不使用于收集性對(duì)象,那么沒有必要自己再設(shè)計(jì)這兩個(gè)函數(shù)的處理方式。這是正確的面向?qū)ο笤O(shè)計(jì)方法,任何用戶一時(shí)用不到的功能,就先不要設(shè)計(jì),以免給日后功能擴(kuò)展帶來(lái)麻煩。

如果你在設(shè)計(jì)時(shí)想別出心裁,不遵守以上的兩套規(guī)則,那么勸你還是不要做這樣想入非非的事。我還沒有遇到過(guò)哪一個(gè)開發(fā)者和我說(shuō)設(shè)計(jì)這兩個(gè)函數(shù)要違背前面說(shuō)的兩個(gè)規(guī)則,我碰到這些違反規(guī)則的情況時(shí),都是作為設(shè)計(jì)錯(cuò)誤處理。

當(dāng)一個(gè)對(duì)象類型作為收集型對(duì)象的元對(duì)象時(shí),這個(gè)對(duì)象應(yīng)該擁有自己處理equals(),和/或處理hashCode()的設(shè)計(jì),而且要遵守前面所說(shuō) 的兩種原則。equals()先要查null和是否是同一類型。查同一類型是為了避免出現(xiàn)ClassCastException這樣的異常給丟出來(lái)。查 null是為了避免出現(xiàn)NullPointerException這樣的異常給丟出來(lái)。

如果你的對(duì)象里面容納的數(shù)據(jù)過(guò)多,那么這兩個(gè)函數(shù) equals()和hashCode()將會(huì)變得效率低。如果對(duì)象中擁有無(wú)法serialized的數(shù)據(jù),equals()有可能在操作中出現(xiàn)錯(cuò)誤。想象 一個(gè)對(duì)象x,它的一個(gè)整型數(shù)據(jù)是transient型(不能被serialize成二進(jìn)制數(shù)據(jù)流)。然而equals()和hashCode()都有依靠 這個(gè)整型數(shù)據(jù),那么,這個(gè)對(duì)象在serialization之前和之后,是否一樣?答案是不一樣。因?yàn)閟erialization之前的整型數(shù)據(jù)是有效的 數(shù)據(jù),在serialization之后,這個(gè)整型數(shù)據(jù)的值并沒有存儲(chǔ)下來(lái),再重新由二進(jìn)制數(shù)據(jù)流轉(zhuǎn)換成對(duì)象后,兩者(對(duì)象在serialization 之前和之后)的狀態(tài)已經(jīng)不同了。這也是要注意的。

知道以上這些能夠幫助你:

1. 進(jìn)行更好的設(shè)計(jì)和開發(fā)。

2. 進(jìn)行更好的測(cè)試案例開發(fā)。

3. 在面試過(guò)程中讓面試者對(duì)你的學(xué)識(shí)淵博感到滿意。

延伸 · 閱讀

精彩推薦
  • Java教程java 中鎖的性能提高辦法

    java 中鎖的性能提高辦法

    這篇文章主要介紹了java 中鎖的性能提高辦法的相關(guān)資料,需要的朋友可以參考下...

    Java之家3092020-08-13
  • Java教程Java list.remove( )方法注意事項(xiàng)

    Java list.remove( )方法注意事項(xiàng)

    這篇文章主要介紹了Java list.remove( )方法注意事項(xiàng),非常簡(jiǎn)單易懂,需要的朋友可以參考下...

    妖久9552021-05-25
  • Java教程JavaWeb 實(shí)現(xiàn)驗(yàn)證碼功能(demo)

    JavaWeb 實(shí)現(xiàn)驗(yàn)證碼功能(demo)

    在 WEB-APP 中一般應(yīng)用于:登錄、注冊(cè)、買某票、秒殺等場(chǎng)景,大家都接觸過(guò)這個(gè)驗(yàn)證碼操作,今天小編通過(guò)實(shí)例代碼給大家講解javaweb實(shí)現(xiàn)驗(yàn)證碼功能,需要...

    java教程網(wǎng)12832020-08-05
  • Java教程JAVA中通過(guò)自定義注解進(jìn)行數(shù)據(jù)驗(yàn)證的方法

    JAVA中通過(guò)自定義注解進(jìn)行數(shù)據(jù)驗(yàn)證的方法

    java 自定義注解驗(yàn)證可自己添加所需要的注解,下面這篇文章主要給大家介紹了關(guān)于JAVA中通過(guò)自定義注解進(jìn)行數(shù)據(jù)驗(yàn)證的相關(guān)資料,文中通過(guò)示例代碼介紹...

    Decouple6362021-05-25
  • Java教程springboot ehcache 配置使用方法代碼詳解

    springboot ehcache 配置使用方法代碼詳解

    EhCache是一個(gè)比較成熟的Java緩存框架,Springboot對(duì)ehcache的使用非常支持,所以在Springboot中只需做些配置就可使用,且使用方式也簡(jiǎn)易,今天給大家分享spri...

    m1719309529412912021-09-16
  • Java教程SpringBoot引入Thymeleaf的實(shí)現(xiàn)方法

    SpringBoot引入Thymeleaf的實(shí)現(xiàn)方法

    這篇文章主要介紹了SpringBoot引入Thymeleaf的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下...

    Bobby6472021-07-28
  • Java教程淺談Java(SpringBoot)基于zookeeper的分布式鎖實(shí)現(xiàn)

    淺談Java(SpringBoot)基于zookeeper的分布式鎖實(shí)現(xiàn)

    這篇文章主要介紹了Java(SpringBoot)基于zookeeper的分布式鎖實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的...

    LJY_SUPER5742021-07-21
  • Java教程Java之Springcloud Feign組件詳解

    Java之Springcloud Feign組件詳解

    這篇文章主要介紹了Java之Springcloud Feign組件詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下...

    深情以改10322021-11-12
主站蜘蛛池模板: 美女扒开胸罩露出胸大乳 | 国内小情侣一二三区在线视频 | 国产精品国产三级国产专区不 | 男人捅女人动漫 | 国产精品久久久久毛片 | 亚洲国产精品成人久久 | 国产在线观看人成激情视频 | 男人的j插入女人的p | 调教全程肉动画片在线观看 | 嫩草影院永久入口在线观看 | 九九精品视频一区二区三区 | 十大免费批日的软件 | 精品一久久香蕉国产线看观 | 国产一级特黄aa大片免费 | 国产精品久久久久无毒 | 青青青久在线视频免费观看 | 四虎永久在线精品国产馆v视影院 | 韩国三级在线观看 完整版 韩国三级视频网站 | 午夜片神马影院福利 | 九九九久久久 | 思思91精品国产综合在线 | 亚洲 综合 自拍 精品 在线 | 91制片厂果冻传媒首页 | 青青色综合 | 国产精品午夜国产小视频 | 欧美精品亚洲精品日韩专区va | 女人麻豆国产香蕉久久精品 | 好吊色视频988gao在线观看 | 91精品婷婷国产综合久久8 | 久久国产精品高清一区二区三区 | 亚洲免费一 | 日本三级免费观看 | 大胆国模一区二区三区伊人 | 日本欧美不卡一区二区三区在线 | 国产日韩免费视频 | 婷婷色天使在线视频观看 | 国产精品短视频 | 亚洲婷婷在线视频 | 国产一区二区三区欧美 | 日本大学jalapsikix | 99热这里只精品99re66 |