【问题标题】:Why HashMap insert new Node on index (n - 1) & hash?为什么HashMap在索引(n - 1)和哈希上插入新节点?
【发布时间】:2015-01-29 14:36:32
【问题描述】:

为什么HashMap在索引上插入新节点: tab[(n - 1) & hash]

在哪里hash = key.hashCode() ^ key.hashCode() >>> 16Node<K,V>数组的n = tab.length

为什么 HashMap 不把 Node 像这样:tab[hash] ?它只是另一个散列函数,例如大多数hashCode() 方法中的乘以 31 吗? 提前感谢您的解释!

【问题讨论】:

  • 提示:n 将是 2 的幂...

标签: java hash collections hashmap hashcode


【解决方案1】:

哈罗德的描述很好,但我觉得没有例子就不够了。所以这是一个 -

每当创建一个新的 Hasmap 时,内部 Node[] 表的数组大小始终是 2 的幂,并且以下方法可以保证它 -

static final int tableSizeFor(int cap) {
    int n = cap - 1;
    n |= n >>> 1;
    n |= n >>> 2;
    n |= n >>> 4;
    n |= n >>> 8;
    n |= n >>> 16;
    return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}

假设您提供的初始容量为 5

cap = 5
n = cap - 1 =  4 = 0 1 0 0
n |= n >>> 1;    0 1 0 0 | 0 0 1 0 = 0 1 1 0 = 6
n |= n >>> 2;    0 0 1 1 | 0 1 1 0 = 0 1 1 1 = 7
n |= n >>> 4;    0 0 0 0 | 0 1 1 1 = 0 1 1 1 = 7
n |= n >>> 8;    0 0 0 0 | 0 1 1 1 = 0 1 1 1 = 7
n |= n >>> 16;   0 0 0 0 | 0 1 1 1 = 0 1 1 1 = 7
return n + 1     7 + 1 = 8 

所以表大小是 8 = 2^3

现在您可以将元素放入 map 中的可能索引值为 0-7,因为表大小为 8。现在让我们看看 put 方法。它按如下方式查找存储桶索引 -

Node<K,V> p =  tab[i = (n - 1) & hash];

其中 n 是数组大小。所以n = 8。和说的一样

Node<K,V> p =  tab[i = hash % n];

所以我们现在只需要看看如何

hash % n == (n - 1) & hash

让我们再举一个例子。假设一个值的哈希是 10。

hash = 10
hash % n = 10 % 8 = 2
(n - 1) & hash = 7 & 10 = 0 1 1 1 & 1 0 1 0 = 0 0 1 0 = 2

希望这会有所帮助。 More details

PS:上面的链接转到我的博客,其中有更详细的示例说明。

【讨论】:

  • 明确的答案。谢谢。
  • 不错的博客。我正在阅读所有帖子:D
【解决方案2】:

因为hash 可能超出范围。

“规范解决方案”是将散列的(正)模与数组的长度取模,此代码使用数组长度为 2 的事实来用变量替换昂贵的模(模常数优化得很好)使用廉价的按位与。

【讨论】:

  • 想了解更多关于这个语句的信息,如果你有时间,“数组有一个二次方的长度,可以用一个变量替换一个昂贵的模(模一个常数被优化得很好)一个便宜的按位与。”无法理解数组如何具有 2 的幂使其优化。如果您参考一些链接或解释。 @aniket-thakur
  • @Tarun 将x % n 替换为x &amp; (n - 1) 的条件是n 必须是2 的幂。 n 在这种情况下是数组的长度。长度为 2 的数组本身不会优化任何东西,但它可以使用该技巧。
  • 谢谢,我知道了。如果 n 是 2 的幂,则 n-1 的格式为 0111....1,这将使 x & (n-1) 等价于 x%n。
猜你喜欢
  • 2015-11-08
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 2014-05-25
  • 2013-04-14
  • 1970-01-01
  • 1970-01-01
  • 2018-07-14
相关资源
最近更新 更多