2013-09-24 17 views
1

我會非常感謝,如果你能清除我的疑問 假設我有一個類A和B A有參考B說b1和b2。 如A類覆蓋等於方法類似的 b1.equal(other.b1)和b2.equal(other.b2)關於哈希碼在java中的實現

並重寫的哈希碼方法類似

int result = 1; 
result = 17* result + ((b1== null) ? 0 : b1.hashCode()); 
result = 17* result + ((b2== null) ? 0 : b2.hashCode()); 
return result; 

是我hashcode方法是否正確實現? 以及如果我打電話給b1.hashcode(),那麼它也會調用類B的哈希碼方法? 如果是的話,那麼強制重寫B類中的equals和hashcode?

在此先感謝。

+0

看起來好像沒什麼問題。 –

+1

此問題似乎是無關緊要的,因爲它涉及代碼質量,屬於[codereview.se]。 –

回答

1

這看起來正確。是的,您應該重寫hashCode並等於B類的方法。

+0

當且僅當它們將繼承的實現不合適時,纔會覆蓋類B中的equals和hashCode方法。如果B直接擴展Object,這意味着如果兩個不同的B實例相等。 –

+0

@PatriciaShanahan我們可以看到OP期望覆蓋B中的等於(請參見問題中的'b1.equal(other.b1)')。如果他這樣做,那麼爲了維護正確的語義,也必須重寫hashCode - 所以我認爲我們同意。 –

+0

是的,如果B需要聲明一個equals方法,而不是繼承它的超類,那麼重寫hashCode來匹配非常非常重要。 –

2

只有在Java中要求hashCode()是一致性。這意味着兩個相同的實例A必須返回相同的哈希碼。如果你的代碼這樣做,那麼你在技術上是好的。這意味着從技術上來說函數簡單地是return 1是有效的。顯然,這是一個糟糕的實現,因爲它具有100%的衝突率。所以爲了做出好的hashCode函數,你也應該儘量減少碰撞率。

就這麼說,你的代碼看起來不錯。

+2

+1,但略有調整:_functional correctness_的唯一要求是相同的對象具有相同的哈希碼。性能是一個真正的需求,即使它沒有在API中正式化。始終從hashCode返回'0'的方式是正確的,就像始終使用冒泡排序排序是正確的一樣;在功能上它是,但它在實踐中在大多數情況下不可用。 – yshavit

+0

是的,你說得對,表現總是很重要。 –

1

看起來不錯,但它可以簡化爲:

int result = ((b1== null) ? 0 : b1.hashCode()); 
result = 17* result + ((b2== null) ? 0 : b2.hashCode()); 
return result; 
+0

那裏幾乎沒有任何簡化。 –

+1

少一行。你可以通過執行'return 17 * result +((b2 == null)?0:b2.hashCode());'來實際取出另一行,但這只是針對垂直空間。這裏沒有真正的優化。 –

+0

我的觀點是,至少有一個原因混合哈希碼與乘數。A)以常數1開始,B)將所述常數乘以17,這可以通過選擇不同的常數來完成,也不需要C)首先將常數加到下一個值。基本上:這並不是簡單的事情,表現上並不重要,但如果這個人用手寫這些,他就會變得冗長冗長。 – James