Hashtable哈希避免负哈希码

时间:2012-09-24 13:54:41

标签: java hash hashtable hashcode

我想知道为什么Hashtable避免使用负哈希码?

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

其中(hash & 0x7FFFFFFF)使得有符号位为0为正,但为什么我们不能将带符号的32位整数视为无符号?甚至使用模块化技巧使其变得积极。例如,

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

6 个答案:

答案 0 :(得分:10)

该值必须介于0tab.length - 1之间,因为它用作内部数组(在本例中为tab)的索引,用于存储值(和溢出元素)。因此,它不能是消极的。

我认为(hash & 0x7FFFFFFF) % tab.length优先使用(hashcode % tab.length + tab.length) % tab.length,因为它会更快而不会过度增加碰撞的机会,但您必须找到设计文档或与原始开发人员交谈才能知道肯定的。

答案 1 :(得分:2)

  

......但为什么我们不能......

您在问为什么选择了特定的实现。没有人可以告诉你,除了代码的原始作者,如果他或她记得。

在代码中实现构思总是有多种方法。编写代码的人必须选择其中一个。事实上,为什么没有选择另一个特定的实现,这没有多大意义。

答案 2 :(得分:2)

如果你的容量保持2的幂,

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

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

基本上,除了您感兴趣的低位之外,屏蔽除了所有位置。假设较低的N位具有与整个哈希码一样的均匀分布。

答案 3 :(得分:1)

Java没有本机无符号类型。如果hashCode具有负值,那么我们必须在我们使用hashCode作为数组索引的任何地方应用此类屏蔽技巧。

答案 4 :(得分:1)

我们不能将signed int视为unsigned,这是一个很明显的理由:原始Java开发人员认为无符号支持是一种不必要的复杂问题,因为无符号算术可以是confusing。从那以后,这对Java来说还不是一个足够大的问题。

作为verdesmerald mentioned,因为没有明确的记录为什么(hash & 0x7FFFFFFF) % tab.length被选择超出你的聪明修改的效果,虽然我们可以找到决定的理由,但最终我们只能推测为什么要这样做。

语义的最后一点,可能并不重要:Hashtable并没有使用负的哈希码,因为哈希码被“翻译”成索引的非负形式。

答案 5 :(得分:0)

除了他自己(也许是他的同事)之外,没有人可以告诉你为什么原始作者选择了该实现。无论如何它并不重要,因为它工作正常。

关于你的建议实施:它可能不会做你应该做的思考。您应该刷新java中的%运算符:For example here。将整数溢出添加到混合中,您建议的表达式可能会导致负值......