2012-09-24 105 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位具有与整个散列码一样的分布。