2009-07-30 164 views
11

我記得eclipse和想法有這個模板來根據它的屬性自動創建一個對象的hashCode。從字符串和int創建哈希

如果使用數字和字符串的策略之一是這樣的。

return stringValue.hashCode() + intValue * 32; 

這種東西就是這樣。

我沒有,也沒有日食或想法在手邊,我想創建這樣的功能。

EDIT

基於I創建這個微型類

class StringInt { 
     private final String s; 
     private final int i; 

     static StringInt valueOf(String string , int value) { 
      return new StringInt(string, value); 
     } 
     private StringInt(String string, int value) { 
      this.s = string; 
      this.i = value; 
     } 
     public boolean equals(Object o) { 
      if(o != null && o instanceof StringInt){ 
       StringInt other = (StringInt) o; 
       return this.s == other.s && this.i == other.i; 
      } 

      return false; 
     } 
     public int hashCode() { 
      return s != null ? s.hashCode() * 37 + i : i; 
     } 
    } 

這個類的答案是要用作鍵大的存儲器映射(> 10K元素)我不希望每次迭代它們以查找String和int是否相同。

謝謝。

ps .. mmh可能它應該是名稱StringIntKey。

+0

奧斯卡,我認爲這是一個很好的課堂。 hashCode方法清晰,可靠且高效。 怎麼樣防止字符串爲空?在你的構造函數中,如果它是null,則拋出一個NPE。然後你可以在equals和hashCode中刪除那些空警號。 最後,爲這樣的問題保留一份「Effective Java」的副本。 Eclipse和IDEA創建的hashCode方法基於該書。 – 2009-07-31 07:23:56

+0

在你的equals方法中,應該比較字符串use equals而不是==。 – 2009-07-31 15:09:12

回答

3

或者,如果你不希望添加另一個庫,請執行以下操作:

public int hashCode() { 
    StringBuilder builder = new StringBuilder(); 
    builder.append(myString); 
    builder.append(myInteger); 
    return builder.toString().hashCode(); 
} 
3

Eclipse中始終沒有大致相同的哈希函數,這是一個有一個在和字符串作爲字段

public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + this.interger; 
     result = prime * result + ((this.string == null) ? 0 : this.string.hashCode()); 
     return result; 
    } 

一類,他們總是選擇31作爲首要的例子,然後通過構建多個哈希函數或者它的原始值。像這樣的東西不難作爲一種方法來創建。

 public int hashCode(Object ... things) { 
     final int prime = 31; 
     int result = 1; 
     for(Object thing : things) { 
      result = prime * result + thing.hashCode(); 
     } 
     return result; 
    } 
0

繼最近的編輯,如果檢索速度比存儲顧慮更重要,你可以預先計算和構造您StringInt類時存儲的哈希碼。這是安全的,因爲您已將Stringint字段標記爲final,並且還確定String是不可變的。

此外,您可以優化您的equals方法,方法是在進行完整比較之前檢查比較對象== this。我還建議在比較字符串字段之前先進行比較便宜的基於int的比較。

另一個最後一個建議:你可以改變你valueOf(String, int)方法要麼建立一個StringInt或者如果已經有一個具有相同String和INT值存在返回先前創建的實例。這使建設更昂貴,但比較非常便宜,因爲您可以使用「==」來比較StringInt,因爲知道將不會使用相同的Stringint值創建兩個StringInt值。

1

哈希碼方法可能被多次調用,因此值得優化。如果計算複雜,則考慮記憶散列值。另外,避免做需要更多計算的事情。 (例如,StringBuilder解決方案大部分時間花費在創建臨時字符串上。)

我想指出的另一件事是散列的質量很重要。您希望避免任何映射大量常用密鑰的哈希碼算法。如果發生這種情況,散列表查找可能不再是O(1)。 (在最壞的情況下,它將是O(N)...即相當於線性搜索!)。這是一個不好的散列函數的例子:

int hashcode() { 
    int hash = 1; 
    for (int val : this.values) { 
     hash = hash * value; 
    } 
    return hash; 
} 

考慮會發生什麼如果this.values一個元素是零......

0

您還可以使用Objects類從java.util.Objects包迅速獲得哈希碼。

@Override 
public int hashCode() { 
    return Objects.hash(this.string, this.integerValue, this.otherDataTypes); 
}