什么哈希函数更好?

时间:2012-02-04 06:58:49

标签: java hashmap hashtable hashcode hash-collision

我用Java编写HashMap的实现。我使用开放寻址来解决冲突。为了更好的密钥分发,我想为密钥的int哈希码使用一个很好的哈希函数。我不知道什么哈希函数对它更好?

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

我需要一个哈希函数来获取密钥的哈希码。

2 个答案:

答案 0 :(得分:3)

任何散布您希望均匀接收的值的散列都是一个很好的散列函数。

您的目标是最大限度地提高性能(在保持正确性的同时最大限度地提高性能)。主要关注的是最小化铲斗碰撞。这意味着理想的哈希值是根据您的输入数据量身定制的 - 如果您知道要接收的内容,则可以选择产生最少数量冲突的哈希值,甚至可以选择缓存最佳访问模式。

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

答案 1 :(得分:1)

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

HashMap使用2的幂并使用以下方法

来避免此问题
 public int getIndex(K key) { return hash(key.hashCode()) & (capacity-1); }

如果容量不是2的幂,你可以忽略高位(通常不是那么随机)

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

实际使用的哈希函数很重要。 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);
}

我会用这个,除非你有充分的理由不这样做。例如。出于安全原因,如果您有可能遭受拒绝服务攻击的服务,您将需要使用不同的哈希来避免恶意用户将您的HashMap转换为LinkedList。不幸的是,您仍然必须使用不同的hashCode(),并且您可以使用基础哈希代码创建一个很长的字符串列表,因此稍后对其进行更改也会更晚。

这是一个字符串列表,其中所有字符串的hashCode()都为0,hash()函数无法做到这一点。

Why doesn't String's hashCode() cache 0?

相关问题