成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

hashcode重寫(xiě)

Mr_houzi / 3131人閱讀

摘要:不同的對(duì)象,建議有不同的。所以最好是讓均勻的落在不同的。正確寫(xiě)法如下要對(duì)兩個(gè)字段做聯(lián)合去重時(shí)皮一下做,做,放入結(jié)果可能為這種情況就是違反了第條,放入了不同的。

我的第一篇文章

以前都在公司的文檔里寫(xiě),后來(lái)想想,還是自己找個(gè)地方記錄下來(lái)吧。
今天有個(gè)朋友問(wèn)我hashcode的問(wèn)題,記錄下來(lái),并稍微讀下書(shū)尋求一點(diǎn)理論知識(shí)。
問(wèn)題如下
有一個(gè)屬性都是字符串的對(duì)象,想放入hashset中,要求,對(duì)某一個(gè)屬性,相同就能放入,不同就不能放入。

朋友的問(wèn)題是,知道equals咋寫(xiě),但是不知道hashcode咋寫(xiě),沒(méi)有思路。

我的理解是:hashcode是一種比equals粗粒度的比較,打個(gè)比方,兩個(gè)三位數(shù),可以拿十位+個(gè)位數(shù)作為hashcode,百位+十位+個(gè)位才是真正的equals。也就是說(shuō),先比較十位+個(gè)位數(shù)hashcode,如果hashcode不一致,那么這兩個(gè)對(duì)象必然不一致,就不用繼續(xù)對(duì)比了,如果十位+個(gè)位數(shù)一致,那么他們有可能是一致的,這時(shí)繼續(xù)對(duì)比equals,才能知道是否兩個(gè)對(duì)象真的一致。當(dāng)然這只是一種粗淺的理解,真正的理解還得看((h = key.hashCode()) ^ (h >>> 16)) & (n-1),直觀上可以理解為就是hash值的補(bǔ)碼取后幾位,問(wèn)題也不大。

public class InnerClass {
    String a;
    String b;
    String c;
    
    @Override
    public boolean equals(Object o) {
        if (this == o) { return true; }
        if (o == null || getClass() != o.getClass()) { return false; }

        InnerClass that = (InnerClass)o;
        return this.a.equals(that.a);
    }

如果只是尋求一個(gè)解,而不是尋求較優(yōu)的解的話,那么很簡(jiǎn)單。不是要比equals粗粒度的比較嗎?隨便來(lái)一個(gè)比equals粗一丁點(diǎn)的就可以了。如下

    @Override
    public int hashCode() {
        return Objects.hash(a);
    }

這個(gè)寫(xiě)法得到的結(jié)果是對(duì)的,但是我總覺(jué)得不好,因?yàn)樵谖业睦斫饫铮琱ashcode也是一種效率上的考慮。這樣的話,和直接比較this.a又有多大區(qū)別呢?

如果強(qiáng)行要粗粒度,我想了一種方法,例如:

    @Override
    public int hashCode() {
        return Objects.hash(a)/3;
    }

這樣其實(shí)也增加不了效率,因?yàn)檎嬲容^的可以理解為hashcode的后幾位,除不除以3,影響不大。

假設(shè)問(wèn)題變成:對(duì)a和b相同的不放入set,那么hashcode用Object.hash(a)才是一種相對(duì)不錯(cuò)的方式。既滿足了要求,又有一定的效率上的提升。

這么閉門(mén)造車(chē)不是個(gè)辦法,拜讀一下《effective java》2e.

整理如下:
1.對(duì)同一個(gè)對(duì)象調(diào)用hashcode時(shí),必須返回同樣的值。
2.equals相同的對(duì)象,必須有相同的hashcode。
3.equals不同的對(duì)象,建議有不同的hashcode。
4.當(dāng)不重寫(xiě)hashcode時(shí),map.put(new A("a"), "b")之后,map.get(new A("a"))不一定能取到"b",因?yàn)闆](méi)重寫(xiě)hashcode,put和get時(shí)的兩個(gè)對(duì)象,都是用的Object的hashcode,因?yàn)閮纱蝞ew是兩個(gè)不同的對(duì)象,所以hashcode不相同,落在不同的bucket。(即便恰好落在相同的bucket,也不一定能獲取到值)
5.hashcode不要返回一個(gè)固定值。返回固定值會(huì)導(dǎo)致,所有值都落在同一個(gè)bucket,這樣程序的時(shí)間復(fù)雜度會(huì)增加。所以最好是讓hashcode均勻的落在不同的bucket。
6.hashcode均勻落在bucket的一個(gè)良好實(shí)踐是:

1.一個(gè)初始值
2.對(duì)對(duì)象的每一個(gè)字段,計(jì)算一個(gè)值(boolean:f?1:0/byte、char、short、int (int)f/long int(f^(f>>>32))/double Double.doubleToLongBits(f),然后按long處理/對(duì)象,對(duì)對(duì)象的每個(gè)字段調(diào)用hashcode
3.result = 31*result + c;

7.對(duì)不包含在equals里對(duì)比的字段,在hashcode中排除掉。
8.對(duì)有意義的字段(即equals里對(duì)比的字段),不要在hashcode中排除。例如要對(duì)a、b做equals,只對(duì)a做hashcode,那么可能hashcode在bucket的分布就不均勻了,性能就會(huì)下降。

根據(jù)這些規(guī)則,發(fā)現(xiàn)以前的很多想法都是錯(cuò)誤的。正確寫(xiě)法如下:

@Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + a.hashCode();
        return result;
    }

要對(duì)a、b兩個(gè)字段做聯(lián)合去重時(shí):

    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + a.hashCode();
        result = 31 * result + b.hashCode();
        return result;
    }

皮一下:
a做equals,a、b做hashcode,放入hashset結(jié)果可能為
b a e
a b c
b c e
這種情況就是違反了第2條,放入了不同的bucket。

之前那個(gè)優(yōu)化的想法不對(duì)(ab做equals,a做hash),因?yàn)閎可能會(huì)導(dǎo)致hashcode在bucket的分布不均勻。

補(bǔ)充:bucket是什么? bucket就是hashmap中包含一系列entry的東西,每個(gè)bucket是一個(gè)鏈表或者一顆樹(shù)。

TODO:
a.hashcode()
object.hash(a)
object.hashcode(a)
的區(qū)別

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/73763.html

相關(guān)文章

  • 面試官讓你說(shuō)說(shuō)==和equals()的區(qū)別,重寫(xiě)equals必須重寫(xiě)hashcode方法嗎

    摘要:如果我們不重寫(xiě)的方法,那么就會(huì)默認(rèn)調(diào)用的方法小王小王我們可以看到以上的運(yùn)行結(jié)果違背了的規(guī)定如果返回,那么方法必須返回相同的整數(shù)所以我們需要對(duì)對(duì)象的方法進(jìn)行重寫(xiě)通過(guò)重寫(xiě)讓其與對(duì)象的屬性關(guān)聯(lián)起來(lái),那么就能夠達(dá)到為,那么的值也相等。 面試官讓你說(shuō)說(shuō)==和equals()的區(qū)別,重寫(xiě)equals必須重寫(xiě)hashcode方法嗎 本身特質(zhì)來(lái)說(shuō) ==:操作符 equals():方法 適用...

    1fe1se 評(píng)論0 收藏0
  • 不同時(shí)重寫(xiě)equals和hashCode又怎樣

    閱讀原文:不同時(shí)重寫(xiě)equals和hashCode又怎樣! 可能一問(wèn)到equals和hashCode相關(guān)的問(wèn)題,就會(huì)有人講他們的自反性,對(duì)稱性,一致性,傳遞性等幾條約定了,此時(shí)我不得不佩服,這么多約定竟然都能記得,但我不知道你是不是真的理解呢。 我不同時(shí)重寫(xiě)又能如何呢? showImg(https://segmentfault.com/img/remote/1460000018795219); 我...

    nifhlheimr 評(píng)論0 收藏0
  • 面試官:“你重寫(xiě)過(guò) hashcode 和 equals 么,為什么重寫(xiě)equals時(shí)必須重寫(xiě)hash

    摘要:介紹的作用是獲取哈希碼,也稱為散列碼它實(shí)際上是返回一個(gè)整數(shù)。所以具有相索引的對(duì)象,在該散列碼位置處存在多個(gè)對(duì)象,我們必須依靠的和本身來(lái)進(jìn)行區(qū)分。 1.hashCode介紹 hashCode() 的作用是獲取哈希碼,也稱為散列碼;它實(shí)際上是返回一個(gè)int整數(shù)。這個(gè)散列碼的作用是確定該對(duì)象在散列表中的索引位置,如果有看我的上一篇文章 什么是散列表,那么這里的散列碼就相當(dāng)于上文中根據(jù)首字母查...

    asce1885 評(píng)論0 收藏0
  • “==”、“equals()”、“hashcode()”之間的秘密

    摘要:它也是用來(lái)判斷兩個(gè)對(duì)象是否相等,所以也得分不同的情況來(lái)說(shuō)明。什么是的作用是獲取哈希碼,也稱為散列碼它返回的一個(gè)整數(shù)。這個(gè)哈希碼的作用是確定該對(duì)象在哈希表中的索引位置。它定義在的中,這就意味著中的任何類都包含有函數(shù)。 前言 萬(wàn)丈高樓平地起,今天的聊點(diǎn)基礎(chǔ)而又經(jīng)常讓人忽視的話題,比如==與equals()區(qū)別?為何當(dāng)我們重寫(xiě)完equals()后也要有必要去重寫(xiě)hashcode()呢? .....

    Richard_Gao 評(píng)論0 收藏0
  • Java equals 和 == 完全解析

    摘要:所以在對(duì)象沒(méi)有重寫(xiě)這個(gè)方法時(shí),默認(rèn)使用此方法,即比較對(duì)象的內(nèi)存地址值。結(jié)果為可以發(fā)現(xiàn)不管對(duì)象的內(nèi)存地址是否相同并不影響其結(jié)果,所以類型比較的是數(shù)據(jù)值而不是內(nèi)存地址值。 showImg(https://segmentfault.com/img/bVbqpku?w=800&h=344); 今天朋友突然問(wèn)到一個(gè)問(wèn)題: 兩個(gè)對(duì)象使用x.equals(y)判斷結(jié)果為true時(shí),兩個(gè)對(duì)象的hash...

    mikasa 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<