2011-03-02 59 views
2

我有一個基於散列的對象集合,如HashSetHashMap。當hashCode()的實現可以隨時間變化時,我可以遇到什麼問題,因爲它是從一些可變域中計算出來的?更改存儲在基於散列的集合中的對象的hashCode

它是如何影響Hibernate的?爲什麼hashCode()默認返回對象的ID是否有缺陷?所有尚未保留的對象的id = 0,如果這很重要。

對於Hibernate映射實體,hashCode的合理實現是什麼?一旦設置ID是不可變的,但在將實體保存到數據庫時不是這樣。

我並不擔心HashSet與十幾個key = 0的實體的性能。我關心的是應用程序和Hibernate是否安全使用ID作爲散列碼,因爲ID會在持久生成時發生變化。

+0

它會影響任何存儲任何基於hashCode的東西,所以如果您需要爲任何g-dam原因改變密鑰,請刪除1st,再次輸入 – bestsss 2011-03-02 22:24:55

+0

我做了一次。花了我幾天的時間才發現這個錯誤。 – 2011-03-02 22:46:34

回答

3

如果同一對象的哈希碼隨時間而改變,結果基本上是不可預測的。哈希集合使用哈希代碼爲對象分配對象 - 如果哈希代碼突然變化,那麼該集合顯然不知道,因此它可能無法找到現有對象,因爲它現在已經哈希到不同的存儲桶。

返回一個對象的ID本身並不壞,但是如果它們中的許多具有id = 0,就會降低哈希表的性能:具有相同哈希代碼的所有對象都會進入同一個存儲桶,所以你的散列表現在不比線性列表好。

更新:從理論上講,你的哈希碼可只要沒人知道它的改變 - 這意味着什麼@bestsss在他的評論,這是從可以持有任何集合刪除您提到的對象並在散列碼更改後再次插入。在實踐中,更好的選擇是從對象的實際內容字段生成哈希碼,而不是依賴數據庫ID。

+0

如何更改持續ID? – 2011-03-02 22:30:28

+0

@Konrad Garus:查看我的更新。 – casablanca 2011-03-02 22:45:19

3

如果對象添加到基於散列的集合,然後發生變異的狀態,從而改變其哈希碼(並暗示可能在.equals()調用的行爲),你可能會看到效果,包括但不僅限於:

  • 的東西,你把收集到似乎沒有有什麼比較
  • 得到的東西哪些是不同的,以你的要求爲

這當然不是你想要的。所以,我建議只使用不可變字段。這通常通過設置字段final並在構造函數中設置它們的值來完成。

0

放置後不要更改基於哈希的集合中的元素的哈希碼。

許多程序員陷入陷阱。 你可能認爲哈希碼是地址集合,所以你不能改變一個元素的地址後,它被放入集合中。

0

Javadoc特意說內置集合不支持這一點。所以不要這樣做。

相關問題