在審查大量的代碼庫,我常常遇到的情況是這樣的:你可以在hashCode()方法中返回一個字段的hashCode()值嗎?
@Override
public int hashCode()
{
return someFieldValue.hashCode();
}
其中編程,而不是產生自己獨特的哈希碼類,簡單地從一個場繼承的哈希碼值。我的直覺(這可能是消化問題)告訴我這是錯誤的,但我不能把它放在手指上。這種實施可能會產生什麼問題?
在審查大量的代碼庫,我常常遇到的情況是這樣的:你可以在hashCode()方法中返回一個字段的hashCode()值嗎?
@Override
public int hashCode()
{
return someFieldValue.hashCode();
}
其中編程,而不是產生自己獨特的哈希碼類,簡單地從一個場繼承的哈希碼值。我的直覺(這可能是消化問題)告訴我這是錯誤的,但我不能把它放在手指上。這種實施可能會產生什麼問題?
這很好,如果你想散列基於單個屬性的對象。
例如,在一個Person
類,你可能有一個唯一標識Person
的ID屬性,所以Person
的hashCode()
可以簡單地是ID的哈希值。另外,hashCode()
與equals
的實施有關。如果兩個對象相同,它們必須具有相同的hashCode
(相反,不一定是正確的 - 兩個不相等的對象可能仍然具有相同的hashCode)。因此,如果相等性由單個屬性(例如唯一ID)確定,那麼hashCode
方法也必須僅使用該單一屬性。
這可以在hashCode的JavaDoc可以看出:
hashCode的一般合同是:
- 每當它是Java的執行期間,在同一對象不止一次上調用應用程序中,只要修改了對象的等號比較中使用的信息,hashCode方法就必須始終返回相同的整數。該整數不需要從應用程序的一次執行到同一應用程序的另一次執行保持一致。
- 如果兩個對象根據equals(Object)方法相等,則對這兩個對象中的每個對象調用hashCode方法必須產生相同的整數結果。
- 根據equals(java.lang.Object)方法,如果兩個對象不相等,則不要求對兩個對象中的每個對象調用hashCode方法必須產生不同的整數結果。但是,程序員應該意識到,爲不相等的對象生成不同的整數結果可能會提高散列表的性能。
我喜歡那句方式的要求是說,代碼知道兩個對象都爲'hashCode()方法返回不同的值'有權假設任何相等比較會產生'FALSE'。當對象被修改時,可變類對象的哈希代碼可以改變*如果*沒有關於其哈希代碼的緩存信息存在於宇宙中的任何地方。即使使用可變類型,代碼通常也可以滿足後者的條件,但不幸的是,沒有自動化的方法來執行要求或確保符合要求。 – supercat 2014-11-24 19:02:04
hashCode()
有去與equals()
。
如果唯一的財產界定equalness是,例如,一個ID,你要照顧好你的哈希碼是等於ID相等時。 完成此操作的最簡單方法是取出您的ID的hashCode()
。
是的,你可以做到這一點從技術上說,你需要的是一個非基本somefieldValue。
從技術上講,你可以可以從hashCode
返回任何一致的數字,即使是一個常數值。唯一requirement the contract places upon you是相等的對象必須返回相同的散列碼:
如果兩個對象根據equals相等(Object)方法,然後調用在每個兩個對象的
hashCode
方法必須產生相同的整數結果。
理論上,如果所有對象的hashCode
都返回0,則合同正式滿足。但是,這使得hashCode
完全無用。
真正的問題是你是否應該做不做。答案取決於你正在返回的哈希碼字段的唯一性。爲對象的hashCode
返回對象的唯一標識符的hashCode
並不罕見。在另一方面,如果對象的顯著比例有someFieldValue
理智的價值,你會使用不同的策略,讓你的對象的哈希碼會更好。
這實際上是罰款。唯一的要求是兩個相等的對象返回相同的散列。這裏就是這種情況。 – ortis 2014-11-24 10:12:01
是的,特別是對於不可變對象。例如,java.lang.String就是這樣做的。 – user11153 2014-11-24 13:59:10
我發現「繼承」是單詞的一個不合理的選擇,因爲Java有一個稱爲繼承的概念,它不涉及這個問題。我會打電話給這個代表團。 – Bryan 2014-11-24 18:13:50