亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

淺談Java中hashCode的正確求值方法

 更新時間:2018年02月01日 10:40:27   作者:司馬懿字仲達  
這篇文章主要介紹了淺談Java中hashCode的正確求值方法,分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下

本文研究的主要是Java中hashCode的正確求值方法的相關(guān)內(nèi)容,具體如下。

散列表有一項優(yōu)化,可以將對象的散列碼(hashCode)緩存起來,如果散列碼不匹配,就不會檢查對象的等同性而直接認(rèn)為成不同的對象。如果散列碼(hashCode)相等,才會檢測對象是否相等(equals)。

如果對象具有相同的散列碼(hashCode),他們會被映射到同一個散列桶中。如果散列表中所有對象的散列碼(hashCode)都一樣,那么該散列表就會退化為鏈表(linked list),從而大大降低其查詢效率。

一個好的散列函數(shù)通常傾向于“為不想等的對象產(chǎn)生不相等的散列碼”。理想情況下,散列函數(shù)應(yīng)該把集合中不想等的實例均勻地分布到所有可能的散列上,但是想要完全達到這種理想的情形是非常困難的,下面給出一個相對簡單有效的散列方法:

1.把某個非零的常數(shù)值,比如說17,保存在一個名為result的int類型的變量中。

2.對于對象中的每個關(guān)鍵域f(指equals方法中涉及的每個域),完成以下步驟:

  • 為該域計算int類型的散列碼c
  • 如果該域是boolean類型,則計算 ( f ? 1 : 0 )
  • 如果該域是byte、char、short或者int類型,則計算 ( ( int ) f )
  • 如果該域是long類型,則計算 ( int ) ( f ^ ( f >>> 32 ) )
  • 如果該域是float類型,則計算Float.floatToIntBits(f)
  • 如果該域是double類型,則計算Double.doubleToLongBits(f),然后按照上述步驟為得到的long類型值再計算散列值
  • 如果該域是一個對象引用,并且該類的equals方法通過遞歸地調(diào)用equals的方式來比較它的域,那么同樣為這個域按上述方法遞歸地調(diào)用hashCode
  • 如果該域是一個數(shù)組,則要把每一個元素當(dāng)作單獨的域來處理,遞歸地應(yīng)用上述原則,如果數(shù)組中的每一個元素都很重要,也可以直接使用Arrays.hashCode方法。
  • 按照下面的公式,把上述步驟得到的散列碼c依次合并到result中:result = 31 * result + c;   乘法運算是為了得到一個更好的散列函數(shù)。比如如果String的散列函數(shù)省略了乘法,那么只是字母順序不同的所有字符串都會有相同的散列碼。這里之所以選擇31,是因為它是一個奇素數(shù)。如果乘數(shù)是偶數(shù),并且乘法溢出的話,信息就會丟失,因為與2相乘等價于位移。使用素數(shù)的好處并不是很明顯,但是習(xí)慣上都使用素數(shù)來計算散列結(jié)果。31有個很好的特性,即用移位和減法來代替乘法,可以得到更好的性能:31 * i == ( i << 5 ) - i?,F(xiàn)在的VM均可以自動實現(xiàn)這種優(yōu)化。

如果一個類是不可變的(所有域都是final修飾,并且所有域都為基本類型或者也是不可變類),并且計算散列碼的開銷也比較大,那么就應(yīng)該考慮把散列碼緩存在對象內(nèi)部。

public class HashCodeDemo {
  static class HashCodeClass {
    private final boolean bResult;
    private final byte byteValue;
    private final char charValue;
    private final short shortValue;
    private final int intValue;
    private final long longValue;
    private final float floatValue;
    private final double doubleValue;
    private final String str;
    private final int[] arrayValue;

    //volatile表示每次均在內(nèi)存中去存取該變量,以保證該變量是最新的
    private volatile int hashCode;

    public HashCodeClass() {
      bResult = false;
      byteValue = 1;
      charValue = 'a';
      shortValue = 1;
      intValue = 1;
      longValue = 1l;
      floatValue = 1.0f;
      doubleValue = 1.0d;
      str = getClass().getName();
      arrayValue = new int[] {1,2,3,4,5};
    }

    @Override
    public int hashCode() {
      if(hashCode == 0) {
        // 設(shè)置一個非零的初始值,可以增加零域的沖突性
        int result = 17;
        // 如果省略乘數(shù),那么只是字母順序不同的所有字符串都會有相同的散列碼
        final int HASH_CODE = 31;
        result = HASH_CODE * result + (bResult ? 1 : 0);
        result = HASH_CODE * result + byteValue;
        result = HASH_CODE * result + charValue;
        result = HASH_CODE * result + shortValue;
        result = HASH_CODE * result + intValue;
        result = HASH_CODE * result + (int) (longValue ^ (longValue >>> 32));
        result = HASH_CODE * result + Float.floatToIntBits(floatValue);
        long doubleLongValue = Double.doubleToLongBits(doubleValue);
        result = HASH_CODE * result + (int) (doubleLongValue ^ (doubleLongValue >>> 32));
        result = HASH_CODE * result + (str == null ? 0 : str.hashCode());
        System.out.println("str=" + str + ", str.hashCode=" + str.hashCode());
        result = HASH_CODE * result + arrayValue.hashCode();
        return result;
      } 
      return hashCode;
    }
  }

  public static void main(String[] args) {
    HashCodeClass obj = new HashCodeClass();
    System.out.println("obj.hashCode=" + obj.hashCode());
    System.out.println("obj="+obj.toString());
  }
}

輸出

str=com.demo.test.HashCodeDemo$HashCodeClass, str.hashCode=-205823051
obj.hashCode=946611167
str=com.demo.test.HashCodeDemo$HashCodeClass, str.hashCode=-205823051
obj=com.demo.test.HashCodeDemo$HashCodeClass@386c23df

總結(jié)

以上就是本文關(guān)于淺談Java中hashCode的正確求值方法的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!

相關(guān)文章

  • SpringBoot任務(wù)之詳解郵件任務(wù)

    SpringBoot任務(wù)之詳解郵件任務(wù)

    今天給大家整理的文章是SpringBoot郵件任務(wù)的相關(guān)知識點,文中有非常詳細(xì)的介紹及代碼示例,對正在學(xué)習(xí)SpringBoot任務(wù)的小伙伴們很有幫助,需要的朋友可以參考下
    2021-06-06
  • Springboot設(shè)置默認(rèn)訪問路徑方法實現(xiàn)

    Springboot設(shè)置默認(rèn)訪問路徑方法實現(xiàn)

    這篇文章主要介紹了Springboot設(shè)置默認(rèn)訪問路徑方法實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • springMVC在restful風(fēng)格的性能優(yōu)化方案

    springMVC在restful風(fēng)格的性能優(yōu)化方案

    這篇文章主要介紹了springMVC在restful風(fēng)格的性能優(yōu)化方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • 詳解使用IntelliJ IDEA 配置Maven(入門)

    詳解使用IntelliJ IDEA 配置Maven(入門)

    本篇文章主要介紹了詳解使用IntelliJ IDEA 配置Maven(入門),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • Spring?Security?自定義授權(quán)服務(wù)器實踐記錄

    Spring?Security?自定義授權(quán)服務(wù)器實踐記錄

    授權(quán)服務(wù)器(Authorization Server)目前并沒有集成在Spring Security項目中,而是作為獨立項目存在于Spring生態(tài)中,這篇文章主要介紹了Spring?Security?自定義授權(quán)服務(wù)器實踐,需要的朋友可以參考下
    2022-08-08
  • 關(guān)于Hystrix的監(jiān)控及可視化面板

    關(guān)于Hystrix的監(jiān)控及可視化面板

    這篇文章主要介紹了關(guān)于Hystrix的監(jiān)控及可視化面板,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • Java工廠模式優(yōu)雅地創(chuàng)建對象以及提高代碼復(fù)用率和靈活性

    Java工廠模式優(yōu)雅地創(chuàng)建對象以及提高代碼復(fù)用率和靈活性

    Java工廠模式是一種創(chuàng)建型設(shè)計模式,通過定義一個工廠類來封裝對象的創(chuàng)建過程,將對象的創(chuàng)建和使用分離,提高代碼的可維護性和可擴展性,同時可以實現(xiàn)更好的代碼復(fù)用和靈活性
    2023-05-05
  • mybatis參數(shù)類型不匹配錯誤argument type mismatch的處理方案

    mybatis參數(shù)類型不匹配錯誤argument type mismatch的處理方案

    這篇文章主要介紹了mybatis參數(shù)類型不匹配錯誤argument type mismatch的處理方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • JDBC的ResultSet使用說明

    JDBC的ResultSet使用說明

    今天小編就為大家分享一篇JDBC的ResultSet使用說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-02-02
  • 關(guān)于springboot集成阿里云短信的問題

    關(guān)于springboot集成阿里云短信的問題

    這篇文章主要介紹了springboot集成阿里云短信的方法,本文通過實例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-11-11

最新評論