Java 在这种情况下,有没有更好的方法来调整哈希值?

Java 在这种情况下,有没有更好的方法来调整哈希值?,java,hash,hashmap,hashcode,hashset,Java,Hash,Hashmap,Hashcode,Hashset,我注意到一个字符串包含一个特定字符的奇数,比如“b”,它的散列值是 kM+r 其中,k和r是整数,M是2的幂。例如,如果M是2的幂(比如16),则调制M后,以下所有字符串产生相同的值: 如果我使用下面的公式()来调整散列值,上面所有的字符串都散列到同一个bucket,这绝对不是我们想要的 int bucket_id = (hashCode(str) & 0x7fffffff) % M; 我在这里做错了什么吗?通常哈希表实现在分配bucket之前对对象哈希代码执行额外的转换。例如,以下

我注意到一个字符串包含一个特定字符的奇数,比如“b”,它的散列值是

kM+r
其中,
k
r
是整数,
M
是2的幂。例如,如果
M
是2的幂(比如16),则调制
M
后,以下所有字符串产生相同的值:

如果我使用下面的公式()来调整散列值,上面所有的字符串都散列到同一个bucket,这绝对不是我们想要的

int bucket_id = (hashCode(str) & 0x7fffffff) % M;

我在这里做错了什么吗?

通常哈希表实现在分配bucket之前对对象哈希代码执行额外的转换。例如,以下是它在OpenJDK 8中的实现方式
java.util.HashMap

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
这使得分布更加均匀。Java-7使用了更复杂的转换,如下所示:

int h = key.hashCode();
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
似乎它被认为是不必要的复杂,因为Java-8简化了它

此外,存储桶被简单地确定为具有
hash(key)&(n-1)
,其中
n
是存储桶的数量。在大多数哈希表实现中,bucket的数量是2的幂,这样的公式很好用


最后,为了更好地防止冲突(意外或故意),在Java 8中实现了一种新算法,该算法在包含过多元素的存储桶中创建一个二叉树(如果键是可比较的)。这使得在过度拥挤的桶中搜索
O(log n)
而不是
O(n)

这非常有用。谢谢
int h = key.hashCode();
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);