2013-03-16 92 views
1

在爲番石榴的ImmutableMap它說的javadoc:性能警告

性能說明:不同的HashMap,ImmutableMap不爲有慢的Object.Equals 元素類型優化(java.lang.Object中)或者 Object.hashCode()實現。您可以通過 讓您的元素類型緩存自己的散列代碼,並使用緩存值的 來短路等效較慢的算法,從而獲得更好的性能。

所以我的第一個問題是如何知道我的元素是否有緩慢的.equals或.hashCode實現?在我的具體實例中,我使用了一個Java Enum作爲我的鍵,因此它有一個有效的.equals和.hashCode默認實現,對嗎? (我假設這些值的實現是無關緊要的,只要你不使用值的值訪問映射)。

我的第二個問題是「讓你的元素類型緩存自己的散列碼」甚至意味着!谷歌搜索我似乎無法找到你如何做到這一點的例子。我假設也許這意味着你最終在hashcodes中的hashcode?所以我進入哈希碼桶,然後.equals方法使用第二組哈希碼內?

回答

4

我使用一個Java枚舉作爲我的鑰匙,讓有.equals和高效的默認實現。 hashCode,對嗎?

不等於或哈希碼被覆蓋,所以它幾乎不會更快(即等於返回this == other)。

我的第二個問題是「讓你的元素類型緩存自己的散列碼」甚至意味着什麼!

你可能有類似下面的代碼,避免多次計算 - 如果你這樣做,你需要確保:

  • 的哈希碼是不變的(即不能在整個改變一個實例的生命)
  • 您的hashcode方法是線程安全的(可以通過使用局部變量來完成,例如,或者更簡單地通過使得hash易變)。
class MyClass { 
    private int hash; 

    public int hashcode() { 
     int hash = this.hash; 
     if (hash == 0) { 
      hash = calculateIt(); 
      this.hash = hash; 
     } 
     return hash; 
    } 
} 
+2

如果對象是不可變的,並且經常調用hashcode()/ equals(),那麼甚至可以在對象構造期間計算哈希碼,而不必擔心線程安全性。 – 2013-03-16 22:50:13

+0

@FrankPavageau絕對 - 確實更容易,更安全。 – assylias 2013-03-16 23:14:34

2

如果你的鑰匙是Enum那麼這對你來說不是問題。

他們與緩存的散列碼談論會是這樣的:

private volatile int hashCode = -1; 

@Override 
public int hashCode() { 
    if (hashCode == -1) { 
    hashCode = longCalculation(); 
    } 
    return hashCode; 
} 
+1

當然,你必須要小心,-1不是一個有效的哈希值。 'java.lang.String'有這個問題:有些字符串每次都會重新計算它們的哈希值。 – Antimony 2013-03-16 21:21:04

+0

你的代碼不是線程安全的 – assylias 2013-03-16 21:22:38

+1

@assylias - 你是對的 - 在某種程度上。實際上,它**是安全的,但如果多個線程同時請求'hashCode',它可以多次調用'longCalculation'。如果這是一個關鍵問題,那麼我肯定會在多線程環境中投入更多精力。但是,它的確清楚地表明瞭我的觀點。 – OldCurmudgeon 2013-03-16 21:26:39