如何生成一個合適的hashcode方法

Hashcode在基於key-value的集合如:HashMap、LinkedHashMap中扮演很重要的角色。此外在HashSet集合中也會運用到,使用合適的hashcode方法在檢索操做時的時間複雜度最好的是 O(1). 算法

一個差勁的hashcode算法不只會下降基於哈希集合的性能,並且會致使異常結果。Java應用中有多種不一樣的方式來生成hashcode。 數組

Effective Java

Josh Bloch在他的書籍《Effective Java》告訴咱們重寫hashcode方法的最佳實踐方式。 app

一個好的hashcode方法一般最好是不相等的對象產生不相等的hash值,理想狀況下,hashcode方法應該把集合中不相等的實例均勻分佈到全部可能的hash值上面。 eclipse

  1. 把某個非0的常數值,好比17,保存在一個名爲result的int類型的變量中。
  2. 對於對象中的每一個域,作以下操做:
    • 爲該域計算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),而後重複第三個步驟。
      • 若是該域是一個對象引用,而且該類的equals方法經過遞歸調用equals方法來比較這個域,一樣爲這個域遞歸的調用hashCode,若是這個域爲null,則返回0。
      • 若是該域是數組,則要把每個元素看成單獨的域來處理,遞歸的運用上述規則,若是數組域中的每一個元素都很重要,那麼可使用Arrays.hashCode方法。

把上面計算獲得的hash值c合併到result中 性能

1
result =31*result + c

String中的Hashcode方法

String的hashcode的算法就充分利用了字符串內部字符數組的全部字符。生成hash碼的算法的在string類中看起來像以下所示,注意「s「是那個字符數組,n是字符串的長度。 ui

1
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

Hashcode使用Eclipse IDE

現代IDE經過點擊右鍵上下文菜單能夠自動生成hashcode方法,經過Eclipse IDE 生成的hashcode像: spa

1
2
3
4
5
6
publicinthashCode() {
finalintprime =31;
intresult =1;
result = prime * result + a;
returnresult;
}

可是並不推薦如上代碼使用在企業級代碼中,最好使用第三方庫如Apache commons來生成hashocde方法。 code

Apache commons HashcodeBuilder

咱們能夠用Apache Commons hashcode builder來生成代碼,使用這樣一個第三方庫的優點是能夠反覆驗證嘗試代碼。下面代碼顯示瞭如何使用Apache Commons hash code 爲一個自定義類構建生成hash code 。 對象

1
2
3
4
5
6
7
publicinthashCode(){
HashCodeBuilder builder =newHashCodeBuilder();
builder.append(mostSignificantMemberVariable);
........................
builder.append(leastSignificantMemberVariable);
returnbuilder.toHashCode();
}

如上面代碼顯示的,最重要的簽名成員變量應該首先傳遞而後跟隨的是沒那麼重要的成員變量。 遞歸

Apache Commons庫一樣爲自定義的類提供了構建生成equals的方法,使用equals構建器的代碼看起來很是像上面的代碼。事實上傳遞給成員變量從最重要的簽名到最不重要的簽名同樣的規則,一樣應用於equals構建器中。

相關文章
相關標籤/搜索