摘要:它也是用來判斷兩個對象是否相等,所以也得分不同的情況來說明。什么是的作用是獲取哈希碼,也稱為散列碼它返回的一個整數(shù)。這個哈希碼的作用是確定該對象在哈希表中的索引位置。它定義在的中,這就意味著中的任何類都包含有函數(shù)。
前言
萬丈高樓平地起,今天的聊點基礎(chǔ)而又經(jīng)常讓人忽視的話題,比如“==”與“equals()”區(qū)別?為何當(dāng)我們重寫完"equals()"后也要有必要去重寫"hashcode()"呢? ... 帶著這些問題,我們一起來探究一下。
概念"==":它主要是判斷符號兩邊的“對象”的值是否相等,而這里的“值“”又有所區(qū)分了。
基礎(chǔ)數(shù)據(jù)類型:比較的就是自身的值,這個跟我們常規(guī)的理解是基本一致的。
引用數(shù)據(jù)類型:比較的對象的內(nèi)存地址。
“equals()”:它也是用來判斷兩個對象是否相等,所以也得分不同的情況來說明。
在當(dāng)前類中,沒有重寫equals方法的話,默認(rèn)的實現(xiàn)跟"=="的實現(xiàn)是一樣的。下面是Object類的equals方法實現(xiàn)。
在當(dāng)前類中,重寫了equals方法,此時判斷的依據(jù)就是你重寫的邏輯。
怎樣重寫equals()方法?1、自反性:對于任何非空引用x,x.equals(x)應(yīng)該返回true。
2、對稱性:對于任何引用x和y,如果x.equals(y)返回true,那么y.equals(x)也應(yīng)該返回true。
3、傳遞性:對于任何引用x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)也應(yīng)該返回true。
4、一致性:如果x和y引用的對象沒有發(fā)生變化,那么反復(fù)調(diào)用x.equals(y)應(yīng)該返回同樣的結(jié)果。
5、非空性:對于任意非空引用x,x.equals(null)應(yīng)該返回false。
由此可以看出,重寫一個equals()方法,需要注意的點還是比較多的,這里給出一個參考的事例。
public class EqualsDemo { private String name; private String info; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; EqualsDemo that = (EqualsDemo) o; if (name != null ? !name.equals(that.name) : that.name != null) return false; return info != null ? info.equals(that.info) : that.info == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (info != null ? info.hashCode() : 0); return result; } }
有些讀者可能會感到奇怪,不是說重寫equals()方法嗎,為什么這里又出現(xiàn)了一個hashcode()?所以這里又引出了我們的另一個主角hashcode()方法,當(dāng)我們重寫了equals()方法后,它就一定會出現(xiàn),也會“吵著“自己也要被重寫。
什么是hashcode()?hashCode() 的作用是獲取哈希碼,也稱為散列碼;它返回的一個int整數(shù)。這個哈希碼的作用是確定該對象在哈希表中的索引位置。hashCode方法的主要作用是為了配合基于散列的集合一起正常運行,這樣的散列集合包括HashSet、HashMap、HashTable等。它定義在JDK的Object.java中,這就意味著Java中的任何類都包含有hashCode() 函數(shù)。
當(dāng)我們在上面的集合插入對象的時候,java是怎么知道里面是否有重復(fù)的對象呢?可能大家第一反應(yīng)是equals方法,沒錯這方法可以實現(xiàn)這個功能,但是當(dāng)集合里面有成千上萬個元素的時候,效率會如何呢?答案當(dāng)然是比較差了,所以才會出現(xiàn)了哈希碼。
public V put(K key, V value) { //判斷當(dāng)前數(shù)組是否等于{},若是則初始化數(shù)組 if (table == EMPTY_TABLE) { inflateTable(threshold); } //判斷 key 是否等于 null,是則將把當(dāng)前鍵值對添加進(jìn)table[0]中,遍歷table[0]鏈表 //如果已經(jīng)有null為key的Entry,則修改值,返回舊值,若無則直接添加。 if (key == null) return putForNullKey(value); //key不為null則計算hash int hash = hash(key); //搜索對應(yīng)hash所在的table中的索引 int i = indexFor(hash, table.length); for (Entrye = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } //修改次數(shù) modCount++; addEntry(hash, key, value, i); return null; }
這里是jdk7中 Hashmap put()方法的實現(xiàn),通過源碼的注釋可以看出執(zhí)行的流程,需要更詳細(xì)的了解HashMap可以參考我之前發(fā)在開源中國的博客《Java7 HashMap全面解讀! 》,鏈接:https://my.oschina.net/199212...
經(jīng)過概念的介紹,知道為什么重寫完equals()后要接著重寫hashcode()了吧?
People p1=new People("小明",18); People p2=new People("小明",18);
此時重寫了equals方法,p1.equals(p2)一定返回true,假如只重寫equals而不重寫hashcode,那么Student類的hashcode方法就是Object默認(rèn)的hashcode方法,由于默認(rèn)的hashcode方法是根據(jù)對象的內(nèi)存地址經(jīng)哈希算法得來的,顯然此時s1!=s2,故兩者的hashcode不一定相等。所以在一些集合的使用當(dāng)中會出現(xiàn)問題。
總結(jié)小小的幾個方法,沒想到卻有這么多“坑”,而且在面試中也會經(jīng)常被問到,在金三銀四的時候,但愿各位不會陷在這里。
喜歡的話,關(guān)注一下微信公眾號《深夜里的程序猿》,每天更新高質(zhì)量IT文章
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/77538.html
摘要:如果我們不重寫的方法,那么就會默認(rèn)調(diào)用的方法小王小王我們可以看到以上的運行結(jié)果違背了的規(guī)定如果返回,那么方法必須返回相同的整數(shù)所以我們需要對對象的方法進(jìn)行重寫通過重寫讓其與對象的屬性關(guān)聯(lián)起來,那么就能夠達(dá)到為,那么的值也相等。 面試官讓你說說==和equals()的區(qū)別,重寫equals必須重寫hashcode方法嗎 本身特質(zhì)來說 ==:操作符 equals():方法 適用...
摘要:介紹的作用是獲取哈希碼,也稱為散列碼它實際上是返回一個整數(shù)。所以具有相索引的對象,在該散列碼位置處存在多個對象,我們必須依靠的和本身來進(jìn)行區(qū)分。 1.hashCode介紹 hashCode() 的作用是獲取哈希碼,也稱為散列碼;它實際上是返回一個int整數(shù)。這個散列碼的作用是確定該對象在散列表中的索引位置,如果有看我的上一篇文章 什么是散列表,那么這里的散列碼就相當(dāng)于上文中根據(jù)首字母查...
摘要:無論在中出現(xiàn)什么,都可以認(rèn)為它是對象除了八大基本數(shù)據(jù)類型。讓當(dāng)前線程等待某個對象的鎖,當(dāng)然應(yīng)該通過這個對象來操作了。但是要注意的是方法調(diào)用后,被喚醒的線程不會立馬獲得到鎖對象。主要的區(qū)別在于在釋放同時,釋放了對象鎖的控制。 前言 五一回家又?jǐn)喔艘粋€放假時間了~~~ 只有光頭才能變強(qiáng) 回顧前面: ThreadLocal就是這么簡單 多線程三分鐘就可以入個門了! 多線程基礎(chǔ)必要知識點!...
摘要:更好的辦法把所有的都到緩沖池去吧最好在用到的時候就進(jìn)行這個操作然后就可以用比較兩個字符串的值了二簡單數(shù)據(jù)類型和封裝類中的和為每一個簡單數(shù)據(jù)類型提供了一個封裝類,每個基本數(shù)據(jù)類型可以封裝成對象類型。 值類型是存儲在內(nèi)存中的堆棧(以后簡稱棧),而引用類型的變量在棧中僅僅是存儲引用類型變量的地址,而其本身則存儲在堆中。 ==操作比較的是兩個變量的值是否相等,對于引用型變量表示的是兩個變量...
摘要:集合判斷兩個元素的標(biāo)準(zhǔn)是兩個對象通過方法比較相等,并且兩個對象的方法返回值也相等。的集合元素也是有序的,以枚舉值在類內(nèi)的定義順序來決定集合元素的順序。是所有實現(xiàn)類中性能最好的,但它只能保存同一個枚舉類的枚舉值作為集合元素。 Set集合通常不能記住元素的添加順序。Set不允許包含重復(fù)的元素。 Set集合不允許包含相同的元素,如果試圖把兩個相同的元素加入同一個Set集合中,則添加操作...
閱讀 3072·2021-11-23 09:51
閱讀 2917·2021-11-11 16:55
閱讀 3019·2021-10-14 09:43
閱讀 1462·2021-09-23 11:22
閱讀 1102·2019-08-30 11:04
閱讀 1786·2019-08-29 11:10
閱讀 1021·2019-08-27 10:56
閱讀 3209·2019-08-26 12:01