2012-09-24 102 views
7

我想知道爲什麼Hashtable避免使用負面哈希碼?哈希表散列避免負面哈希碼

int hash = key.hashCode(); 
int index = (hash & 0x7FFFFFFF) % tab.length; 

(hash & 0x7FFFFFFF)使符號位爲0到積極的,但我們爲什麼不能把簽名的32位整數爲unsigned?或者甚至使用模塊化技巧使其變得積極。例如,

public static long int_mod(int hashcode, int tab_length){ 
    return (hashcode % tab_length + tab_length) % tab_length; 
} 
+0

我覺得這個方法很簡單,也適用。可能這就是它被使用的原因。 '(hash&0x7FFFFFFF)'窄到正值,'%tab.length'窄到標籤大小。簡單幹淨,方便。 –

+0

你指的是哪一種方法?原始實施? – peter

+0

是的。已經實施。 –

回答

9

值必須是0tab.length - 1之間因爲它是用來作爲一個指數到(在這種情況下tab)的內部陣列中存儲的值(和溢出元件)。因此,它不能是負面的。

我認爲​​優先於(hashcode % tab.length + tab.length) % tab.length使用,因爲它速度更快而不會過度增加碰撞的可能性,但是您必須找到設計文檔或與原始開發人員進行交談,以便確切知道。

2

...但是我們爲什麼不能?

你問爲什麼選擇一個特定的實現。如果他或她記得,沒有人可以告訴你,除了代碼的原始作者。

在代碼中總是有多種方法來實現一個想法。編寫代碼的人必須選擇其中之一。在事實之後,爲什麼沒有選擇另一個特定的實施方案,這並沒有什麼意義。

+0

我提議工作的想法也是如此嗎? – peter

+0

我沒有檢查過,但我想是的。爲什麼你不滿意它是如何實現的? – Jesper

+1

我很高興。我只是想知道其他的替代品 – peter

1

Java沒有原生的無符號類型。如果hashCode會有負值,那麼在我們使用hashCode作爲數組索引的任何地方,我們都必須應用這樣的屏蔽技巧。

0

沒有人可以告訴你關於爲什麼原始作者選擇了實現,除了他自己(也可能是他的同事)。無論如何,這並不重要,因爲它工作正常。

關於你的建議實現:它可能不會做你認爲它應該做的。你應該刷新java中的%運算符:For example here。將整數溢出添加到混合中,並且您的建議表達式可能會導致負值...

1

有一種表面上很重要的原因,我們不能將signed int當作unsigned來處理:原始Java開發人員認爲unsigned support是不必要的複雜性,因爲無符號算術可以是confusing。對於Java來說,這並不是一個足夠大的問題。

由於verdesmerald mentioned,因爲就是爲什麼​​被選擇了東西到你的巧妙改裝的效果,雖然我們可以找到理由的決定,最終我們只能推測爲什麼要製作它沒有明確的記錄。

語義學的最後一點,可能並不那麼重要:它並不是說哈希表不使用負面的哈希碼,因爲哈希碼被「翻譯」爲索引的非負形式。

2

如果你把你的容量爲2的冪,

private static final int CAPACITY = 64; 
private static final int HASH_MASK = CAPACITY - 1; 

final int index = obj.hashCode() & HASH_MASK; 

基本上,屏蔽掉所有,但低位在你有興趣。假設較低的N位具有與整個散列碼一樣的分佈。