2010-05-31 97 views
21

我有一個使用hashCode()實現的向量類。它不是由我寫的,而是使用2個素數來乘以2個矢量分量,然後對它們進行異或運算。這是它:將Java哈希碼組合成「主」哈希碼

/*class Vector2f*/ 
... 
    public int hashCode() 
    { 
     return 997 * ((int)x)^991 * ((int)y); //large primes! 
    } 

...因爲這是來自已建立的Java庫,我知道它的工作原理很好。

然後,我有一個邊界類,它包含2個向量,「開始」和「結束」(表示一行的終點)。這兩個向量的值是描述邊界的特徵。

/*class Boundary*/ 
... 
    public int hashCode() 
    { 
     return 1013 * (start.hashCode())^1009 * (end.hashCode()); 
    } 

在這裏,我試圖爲載體的獨特的2元組創建一個良好的hashCode()(啓動&端)構成該邊界。我的問題:這個hashCode()實現是否正常工作? (注意,我在後面的hashCode()實現中使用了2個不同的素數;我不知道這是否是必要的,但是當試圖避免常見因素時比對不起更好,我猜 - 自從我認爲這就是爲什麼素數在哈希函數中很受歡迎的原因。)

回答

16

這是正常的做法。我看起來很合理。如果您使用的是Eclipse,您應該會發現它可以爲您生成equalshashCode - 只需檢查菜單。它會做同樣的事情 - 列舉你的領域,並創建一個檢查所有這些方法的equals方法,然後選擇n素數,並且做你已經做了什麼來創建一個hashCode方法。

+0

謝謝薩米爾,我不知道Eclipse有這個。 – 2010-05-31 12:24:49

3

使用素數(它們不一定是「大」素數)的原因確實是爲了避免常見因素。

散列碼由基於散列的集合類使用,例如HashSetHashMap。如果地圖中對象的散列碼儘可能不相似,它們的效果最好(如果這些對象的散列碼相同,則它們必須做更多的工作來區分對象)。

將您用於製作組合散列碼的部分的散列碼與素數相乘,可確保部件不會有公共因素,因此碰撞的可能性較小(關於不同部分的散列碼與每個部分重疊其他)。

+0

就這樣,我得到這個權利,是否建議我在Boundary.hashCode()中使用一個*不同的素數對*作爲基礎Vector2f.hashCode()實現中使用的對?或者,如果我在997和991中都使用了它們,那麼它們會一樣嗎? AFAIK,由於XOR是旋轉位,因此XOR產生的整數不一定是素數(或非素數),這意味着如果我使用同一對素數應該沒有關係? – 2010-05-31 12:24:03

+0

我不完全確定;如果使用+而不是XOR,那麼很明顯 - 你應該使用不同的素數。所以我會這樣做,以確保安全。請注意,XOR幾乎就像添加數字一樣,但不攜帶比特(即「1^1 = 0」而不是「10」,前進一位)。我沒有想過這究竟會如何影響結果。 – Jesper 2010-05-31 13:20:03

+0

@Nick Wiggill我認爲重要的是,素數乘以不是hashTable底層數組大小的一個因素。如果你乘以17,並且數組的大小是34,那麼所有的對象將會在0或17的位置結束(導致大量的衝突)。 – ILMTitan 2010-06-01 15:13:19