【问题标题】:Explanation of HashMap#hash(int) methodHashMap#hash(int)方法的解释
【发布时间】:2011-01-25 17:26:45
【问题描述】:

有人可以向我解释一下静态 HashMap#hash(int) 方法吗?

生成均匀分布的哈希的理由是什么?

/**
 * 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);
}

举个例子会更容易理解。

澄清 我知道运算符、真值表和按位运算。我真的无法真正解码实现,也无法真正解码评论。甚至是背后的原因。

标签: java hash hashmap


【解决方案1】:

>>> 是逻辑右移(无符号扩展)(JLS 15.19 Shift Operators),^ 是按位异或(JLS 15.22.1 Integer Bitwise Operators)。

至于这样做的原因,文档提供了一个提示:HashMap 使用二次幂长度表,并通过屏蔽高位并仅获取其哈希码的低位来对密钥进行哈希处理。

// HashMap.java -- edited for conciseness
static int indexFor(int h, int length) {
    return h & (length-1);
}

public V put(K key, V value) {
    int hash = hash(key.hashCode());
    int index = indexFor(hash, table.length);
    // ...
}

所以hash() 试图将相关性带到更高位,否则会被屏蔽掉(indexFor 基本上丢弃了h 的更高位,并且只占用了length == (1 << k) 的较低k 位)。

Hashtable(不应该有一个2的幂长度表)使用键的哈希码的方式进行对比。

// Hashtable.java -- edited for conciseness
public synchronized V get(Object key) {
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % table.length;
    // ...
}

通过执行更昂贵的% 操作(而不是简单的位掩码),Hashtable 的性能对低位分布不佳的哈希码不太敏感(特别是如果table.length 是质数) .

【讨论】:

  • 嗯,这确实是我关心的事情 TBH :)
  • 请注意,如果他们使用二次幂表(我想他们没有),% 与位掩码的作用相同。
  • @Thilo,默认初始 = 11,调整大小为 int newCapacity = oldCapacity * 2 + 1;,因此他们正在积极避免两个幂,以充分利用代价高昂的 % 操作。
【解决方案2】:

我不知道所有的转换是如何工作的,但动机是在 cmets 中列出的:

HashMap 的实现方式依赖于 hashCode 函数的实现是否足够好。特别是,哈希值的低位应该均匀分布。如果低位有很多冲突,HashMap 将无法正常运行。

因为 hashCode 的实现不受 HashMap 的控制(每个对象都可以实现自己的),所以它们提供了一个额外的哈希函数,可以稍微移动对象的 hashCode 以确保低位分布更随机。同样,我不知道这究竟是如何工作的(或者它有多有效),但我认为它至少取决于平均分配的较高位(它似乎将较高位网格化到较低位中)。

因此,这样做的目的是在存在实施不佳的 hashCode 方法的情况下尽量减少冲突(从而提高性能)。

【讨论】:

    猜你喜欢
    • 2016-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-07
    • 2018-06-27
    • 2011-09-17
    • 2020-04-24
    • 1970-01-01
    相关资源
    最近更新 更多