重寫equals 和hashcode

1. 哪些類型的數(shù)據(jù)會(huì)使用equals 方法淆党?

所有java 的所有的對象都可以使用該方法比較兩個(gè)對象是否相等唯咬。

2. equals 默認(rèn)比較的是對象的什么值段只?

不重寫時(shí)趣惠,equals 方法默認(rèn)比較的是對象的引用是否指向同一塊內(nèi)存地址
重寫equals 的目的是為了比較兩個(gè)對象的 value 值是相等
hashcode 的存在主要是為了查找的快捷性狸棍,因?yàn)樗怯脕泶_定對象在內(nèi)存中的存儲(chǔ)地址,比如我們需要將一個(gè)字段id 的值存放在內(nèi)存的0,1,2,3,4,5,6,7 這八個(gè)位置中味悄,那應(yīng)該把它存放在內(nèi)存中的哪個(gè)位置呢草戈,這時(shí)候就需要根據(jù)散列存儲(chǔ)結(jié)構(gòu)中計(jì)算對象的hashcode 值的方法:id%8 , 獲得該對象在內(nèi)存中的存放位置,但是這樣可能有多個(gè)不同對象計(jì)算的hashcode 相同侍瑟,所以唐片,可能同一個(gè)位置會(huì)存放多個(gè)的對象,所以說判斷兩個(gè)對象是否相等時(shí)涨颜,hashcode方法返回該對象的哈希碼值费韭, 會(huì)先通過hashcode 方法快速找到它在內(nèi)存中的存放位置,然后再通過equals 方法找到我們需要的對象庭瑰。
所以重寫equals 方法的同時(shí)星持,必須重寫hashcode 方法,因?yàn)楦鶕?jù)hashcode 的協(xié)定弹灭,相等的對象必須具有相等的哈希嗎钉汗。

hashCode用于返回對象的hash值,主要用于查找的快捷性鲤屡,因?yàn)閔ashCode也是在Object對象中就有的损痰,所以所有Java對象都有hashCode,在HashTable和HashMap這一類的散列結(jié)構(gòu)中酒来,都是通過hashCode來查找在散列表中的位置的卢未。

3. Java里面有==運(yùn)算符了,為什么還需要equals啊辽社?

equals和hashCode都是Object對象中的非final方法
equals()的作用是用來判斷兩個(gè)對象是否相等伟墙,在Object里面的定義是:

public boolean equals(Object obj) {
    return (this == obj);
}

這里可以看到在實(shí)現(xiàn)我們自己的equals 之前, equals 等價(jià)于 == , 而== 運(yùn)算符判斷的是兩個(gè)對象是不是同一個(gè)對象滴铅,即他們的地址是否相等戳葵。而重寫equals 目的是比較兩個(gè)對象在邏輯上的相等,可以說是值相等汉匙,也可以說是內(nèi)容相等拱烁。

  • 覆寫equals時(shí)有哪些準(zhǔn)則?

自反性: 對于任何非空引用值x, x.equals(x) 都應(yīng)該返回true

對稱性: 對于任何非空引用值 x 和 y噩翠, 當(dāng)且僅當(dāng)x.equals(y) 返回true 時(shí)戏自, y.equals(x) 才應(yīng)該返回true。

傳遞性:對于任何非空引用值 x伤锚、y 和 z擅笔,如果 x.equals(y) 返回 true, 并且 y.equals(z) 返回 true屯援,那么 x.equals(z) 應(yīng)返回 true猛们。

一致性:對于任何非空引用值x,y , 多次調(diào)用x.eqauls(y) 始終返回true或者始終返回false狞洋,前提是對象equals 比較中所用的額信息沒有被修改阅懦。

非空性:對于任何非空引用值x, x.equals(null)都應(yīng)該返回false

4. 什么場景下重寫equals 方法?

在我們的業(yè)務(wù)系統(tǒng)中判斷對象時(shí)有時(shí)候需要的不是一種嚴(yán)格意義上的相等徘铝,而是一種業(yè)務(wù)上的對象相等耳胎,即值相等或者說內(nèi)容相等。在這種情況下惕它,原生的equals方法就不能滿足我們的需求了怕午,所以我們需要重寫equals 方法來實(shí)現(xiàn)在比較兩個(gè)對象時(shí)只比較值相等即可。

5. 如何重寫equals 方法 和hashcode 方法淹魄?

@Override
public boolean equals(Object object) {
//    //測試檢測的對象是否為空郁惜,是就返回false
        if (object == null) {
            return false;
        }

//使用==操作符檢查“參數(shù)是否為這個(gè)對象的引用”:如果是對象本身,則直接返回甲锡,攔截了對本身調(diào)用的情況兆蕉,算是一種性能優(yōu)化。
        if (object == this) {
            return true;
        }

//使用instanceof操作符檢查“參數(shù)是否是正確的類型”:如果不是缤沦,就返回false
// 在 equals() 中最好使用 getClass 進(jìn)行類型判斷,
        if (!(object instanceof HashTest)) {
            return false;
        }
或者
 //測試兩個(gè)對象所屬的類是否相同虎韵,否則返回false
         if (this.getClass() != object.getClass()){
             return false
         }

       //對object進(jìn)行類型轉(zhuǎn)換以便和類A的對象進(jìn)行比較
                A other=(A)otherObject;

        if (object.getI() == this.getI()) {
            return true;
        }
        return false;
}

@Override
public int hashCode() {
        return id.hashCode();
    }

或者
@Override
 public int hashCode() {
        int hash = 17;
        hash = hash * 31 + getName().hashCode();
        return hash;
    }

//或者有更簡單的方法
@Override
public int hashCode()
{
    return Object.hashCode(屬性A,屬性B缸废,屬性C包蓝,……);
}

//關(guān)于hashCode()計(jì)算過程中驶社,為什么使用了數(shù)字31,主要有以下原因:
1测萎、使用質(zhì)數(shù)計(jì)算哈希碼亡电,由于質(zhì)數(shù)的特性,它與其他數(shù)字相乘之后硅瞧,計(jì)算結(jié)果唯一的概率更大份乒,哈希沖突的概率更小。
2腕唧、使用的質(zhì)數(shù)越大或辖,哈希沖突的概率越小,但是計(jì)算的速度也越慢四苇;31是哈希沖突和性能的折中,實(shí)際上是實(shí)驗(yàn)觀測的結(jié)果方咆。
3月腋、JVM會(huì)自動(dòng)對31進(jìn)行優(yōu)化:31 * i == (i << 5) – i

關(guān)于hashcode 的重寫請參考:http://www.importnew.com/25783.html
需要注意的地方:
  • 我們在覆寫 equals() 方法時(shí),一般都是推薦使用 getClass 來進(jìn)行類型判斷瓣赂,不是使用 instanceof
原因:我們都清楚 instanceof 的作用是判斷其左邊對象是否為其右邊類的實(shí)例榆骚,返回 boolean 類型的數(shù)據(jù)。
可以用來判斷繼承中的子類的實(shí)例是否為父類的實(shí)現(xiàn)煌集。注意后面這句話:可以用來判斷繼承中的子類的實(shí)例是否為父類的實(shí)現(xiàn)妓肢,正是這句話在作怪。
具體例子請參考:http://wiki.jikexueyuan.com/project/java-enhancement/java-thirteen.html
  • 覆蓋equals時(shí)一定要覆蓋hashCode
  • equals函數(shù)里面一定要是Object類型作為參數(shù)
  • equals方法本身不要過于智能苫纤,只要判斷一些值相等即可
特性:

如果兩個(gè)對象equals碉钠,那么它們的hashCode必然相等,
但是hashCode相等卷拘,equals不一定相等喊废。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市栗弟,隨后出現(xiàn)的幾起案子污筷,更是在濱河造成了極大的恐慌,老刑警劉巖乍赫,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瓣蛀,死亡現(xiàn)場離奇詭異,居然都是意外死亡雷厂,警方通過查閱死者的電腦和手機(jī)惋增,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來改鲫,“玉大人器腋,你說我怎么就攤上這事。” “怎么了纫塌?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵诊县,是天一觀的道長。 經(jīng)常有香客問我措左,道長依痊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任怎披,我火速辦了婚禮胸嘁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘凉逛。我一直安慰自己性宏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布状飞。 她就那樣靜靜地躺著毫胜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪诬辈。 梳的紋絲不亂的頭發(fā)上酵使,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天,我揣著相機(jī)與錄音焙糟,去河邊找鬼口渔。 笑死,一個(gè)胖子當(dāng)著我的面吹牛穿撮,可吹牛的內(nèi)容都是我干的缺脉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼悦穿,長吁一口氣:“原來是場噩夢啊……” “哼枪向!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起咧党,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤秘蛔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后傍衡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體深员,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年蛙埂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了倦畅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,015評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡绣的,死狀恐怖叠赐,靈堂內(nèi)的尸體忽然破棺而出欲账,到底是詐尸還是另有隱情,我是刑警寧澤芭概,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布赛不,位于F島的核電站,受9級特大地震影響罢洲,放射性物質(zhì)發(fā)生泄漏踢故。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一惹苗、第九天 我趴在偏房一處隱蔽的房頂上張望殿较。 院中可真熱鬧,春花似錦桩蓉、人聲如沸淋纲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽洽瞬。三九已至,卻和暖如春儡首,著一層夾襖步出監(jiān)牢的瞬間片任,已是汗流浹背偏友。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工蔬胯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人位他。 一個(gè)月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓氛濒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鹅髓。 傳聞我的和親對象是個(gè)殘疾皇子舞竿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內(nèi)容