Java 什么散列函数更好?

Java 什么散列函数更好?,java,hashmap,hashtable,hashcode,hash-collision,Java,Hashmap,Hashtable,Hashcode,Hash Collision,我用Java编写HashMap的实现。我使用开放寻址来解决冲突。为了更好地分配密钥,我希望对密钥的inthashcode使用一个好的哈希函数。我不知道什么哈希函数更适合它 public int getIndex(K key) { return hash(key.hashCode()) % capacity; } 我需要一个哈希函数来表示密钥的hashcode。任何平均分配期望接收的值的哈希函数都是一个好的哈希函数 您的目标是最大化性能(好吧,在保持正确性的同时最大化性能)。主要关注的是尽量减少

我用Java编写HashMap的实现。我使用开放寻址来解决冲突。为了更好地分配密钥,我希望对密钥的
int
hashcode使用一个好的哈希函数。我不知道什么哈希函数更适合它

public int getIndex(K key) { return hash(key.hashCode()) % capacity; }

我需要一个哈希函数来表示密钥的hashcode。

任何平均分配期望接收的值的哈希函数都是一个好的哈希函数

您的目标是最大化性能(好吧,在保持正确性的同时最大化性能)。主要关注的是尽量减少铲斗碰撞。这意味着理想的散列是根据您的输入数据定制的——如果您知道将接收到什么,您可以选择产生最小数量冲突的散列,甚至可能是缓存最佳访问模式


然而,这通常不是一个现实的选项,所以您只需选择一个输出无偏且不可预测的散列(其行为类似于伪随机数生成器,但具有确定性)。一些这样的函数是“杂音”散列函数族。

任何平均分配期望接收的值的散列函数都是好的散列函数

您的目标是最大化性能(好吧,在保持正确性的同时最大化性能)。主要关注的是尽量减少铲斗碰撞。这意味着理想的散列是根据您的输入数据定制的——如果您知道将接收到什么,您可以选择产生最小数量冲突的散列,甚至可能是缓存最佳访问模式


然而,这通常不是一个现实的选项,所以您只需选择一个输出无偏且不可预测的散列(其行为类似于伪随机数生成器,但具有确定性)。一些这样的函数是“杂音”散列族。

使用
%容量的主要问题是它可以返回负值和正值

HashMap使用2的幂避免了这个问题,并使用以下方法

 public int getIndex(K key) { return hash(key.hashCode()) & (capacity-1); }
如果容量不是2的幂,可以忽略高位(通常不是随机的)

实际使用的哈希函数可能很重要。HashMap使用以下内容

/**
 * Applies a supplemental hash function to a given hashCode, which
 * defends against poor quality hash functions.  This is critical
 * because HashMap uses power-of-two length hash tables, that
 * otherwise encounter collisions for hashCodes that do not differ
 * in lower bits. Note: Null keys always map to hash 0, thus index 0.
 */
static int hash(int h) {
    // This function ensures that hashCodes that differ only by
    // constant multiples at each bit position have a bounded
    // number of collisions (approximately 8 at default load factor).
    h ^= (h >>> 20) ^ (h >>> 12);
    return h ^ (h >>> 7) ^ (h >>> 4);
}
我会用这个,除非你有充分的理由不这么做。例如,出于安全原因,如果您的服务可能受到拒绝服务攻击,您将希望使用不同的散列,以避免恶意用户将您的散列映射转换为LinkedList。不幸的是,您仍然必须使用不同的hashCode(),还可以使用底层的hash代码创建一长串字符串,因此以后对其进行变异就太晚了

下面是一个字符串列表,其中所有字符串的hashCode()值均为0,而hash()函数对此无能为力


使用
%容量的主要问题是它可以返回负值和正值

HashMap使用2的幂避免了这个问题,并使用以下方法

 public int getIndex(K key) { return hash(key.hashCode()) & (capacity-1); }
如果容量不是2的幂,可以忽略高位(通常不是随机的)

实际使用的哈希函数可能很重要。HashMap使用以下内容

/**
 * Applies a supplemental hash function to a given hashCode, which
 * defends against poor quality hash functions.  This is critical
 * because HashMap uses power-of-two length hash tables, that
 * otherwise encounter collisions for hashCodes that do not differ
 * in lower bits. Note: Null keys always map to hash 0, thus index 0.
 */
static int hash(int h) {
    // This function ensures that hashCodes that differ only by
    // constant multiples at each bit position have a bounded
    // number of collisions (approximately 8 at default load factor).
    h ^= (h >>> 20) ^ (h >>> 12);
    return h ^ (h >>> 7) ^ (h >>> 4);
}
我会用这个,除非你有充分的理由不这么做。例如,出于安全原因,如果您的服务可能受到拒绝服务攻击,您将希望使用不同的散列,以避免恶意用户将您的散列映射转换为LinkedList。不幸的是,您仍然必须使用不同的hashCode(),还可以使用底层的hash代码创建一长串字符串,因此以后对其进行变异就太晚了

下面是一个字符串列表,其中所有字符串的hashCode()值均为0,而hash()函数对此无能为力


你的问题一点也不清楚。您是在重新实现HashMap(为什么?)还是在为希望用作HashMap键的类编写hashCode()方法?在您的示例中,为什么要对键提供的哈希代码进行哈希处理?您的问题一点也不清楚。您是在重新实现HashMap(为什么?)还是在为希望用作HashMap键的类编写hashCode()方法?在您的示例中,为什么要对键提供的哈希代码进行哈希?