2010-06-13 83 views
8

除了允許使用散列表之外,還有其他什麼原因可以爲我的類型實現散列碼功能嗎?什麼時候應該爲我的類型定義一個哈希碼函數?

假設我正在設計一些我打算在內部使用的類型。我知道類型是系統的「內部」,我也知道我絕不會在散列表中使用這些類型。儘管如此,我決定我將不得不重新定義equals()方法。理論上說我也應該重新定義哈希碼的方法,但我看不出任何理由,在這種情況下,我應該這樣做。

任何人都可以指出我的其他原因嗎?

這個問題可以改爲:在哪些情況下我們應該在我們的類型中實現一個哈希碼方法。

PS:我不是問如何實現一個。我在詢問

回答

10

可能不會 - 但你的任何代碼,例如,將使用LINQ?有許多意想不到的地方可能會在你的數據上使用散列表或字典。

如果您不想意外......「有趣」,那麼如果您更改Equals,請覆蓋GetHashCode。同樣,任何IEquatable<T>.Equals都應該與object.Equals實現相匹配。

+0

+1意外的「樂趣」。尼斯轉身,馬克! – spender 2010-06-13 22:05:48

4

在這種情況下我們應該在我們的類型中實現一個哈希碼方法。

簡答:只要您覆蓋.Equals。因爲框架設計指南是這樣說的。

6

是的,絕對。 hashCode和equals在同一事物上有兩個視圖,並且必須一致。集合中的許多例程使用散列碼,如果它告訴不同於等於的東西,就會開始行爲不端。您可以將「行爲不端」理解爲「難以置信地發現導致早期頭髮流失的錯誤」。

如果您覆蓋等於,您必須忽略散列碼,而不是因爲指導說明如此,而是因爲您重視您的頭髮(或時間)。

現代IDE爲您和來自Java Commons或Spring的EqualsBuilder/HashCodeBuilder生成良好的equals/hashcode可以使它更容易。龍目島項目即時生成它們。

這是一件嚴重的事情,用這些方法可以做的最好的事情是正確的,並且有成百上千種做錯的方式,導致痛苦和痛苦。如果您可以避免自己編寫它們,那麼請使用生成器或庫來幫助您。

+0

Resharper早餐吃平等執行。點,clickety點擊,去。 – spender 2010-06-13 22:07:47

+1

IntelliJ:Alt-Ins(Ctrl-N)+用光標+ Enter選擇「生成等於/哈希碼」。 Eclipse和Netbeans相似。 他們有一個缺點:如果你使用代碼度量,這些例程由於圈複雜性而不能遵循所有代碼中的所有軌跡,因此這些例程突出顯示爲痛苦的拇指。所以他們創造了一個可以隱藏其他惡劣程序的環境。 EqualsBuilder/HashcodeBuilder沒有這個問題。 – 2010-06-13 22:18:32

+0

*「......但是因爲你重視你的頭髮(或時間)」*。或者生活,如果一個同事必須解決你的混亂。 :-) – 2010-06-13 23:53:38

0

如果你確定你的對象不會在散列表中使用,並且沒有使用散列碼,那麼你可以重寫hashCode來拋出一個「未實現」的異常。這比不重寫更安全,因爲它明確禁止使用該方法,並避免了否則會導致的顯着錯誤。它還會清楚地告訴你該方法是否已被使用。

但是,我個人認爲只是使用IDE來生成一個與Equals一致並且可以完成的合理實現。它通常是覆蓋equals的值類型,在測試這些時,通常會使用maps,所以實現equals/hashcode API所需的完整合約是有意義的。

相關問題