【发布时间】:2018-06-10 10:58:01
【问题描述】:
我试图了解在超过占用的存储桶数或所有存储桶中的条目总数时会发生哈希映射的重新散列。意思是,我们知道如果 16 个桶中的 12 个(每个桶中有一个条目)已满(考虑默认负载因子和初始容量),那么我们知道在下一个条目上哈希图将被重新散列。但是如果假设只有 3 个存储桶被每个 4 个条目占用(总共 12 个条目,但 16 个存储桶中只有 3 个在使用中),那该怎么办?
所以我尝试通过制作最差的哈希函数来复制这一点,它将所有条目放在一个桶中。
这是我的代码。
class X {
public Integer value;
public X(Integer value) {
super();
this.value = value;
}
@Override
public int hashCode() {
return 1;
}
@Override
public boolean equals(Object obj) {
X a = (X) obj;
if(this.value.equals(a.value)) {
return true;
}
return false;
}
}
现在我开始将值放入 hashmap 中。
HashMap<X, Integer> map = new HashMap<>();
map.put(new X(1), 1);
map.put(new X(2), 2);
map.put(new X(3), 3);
map.put(new X(4), 4);
map.put(new X(5), 5);
map.put(new X(6), 6);
map.put(new X(7), 7);
map.put(new X(8), 8);
map.put(new X(9), 9);
map.put(new X(10), 10);
map.put(new X(11), 11);
map.put(new X(12), 12);
map.put(new X(13), 13);
System.out.println(map.size());
所有节点都按预期进入了单个存储桶,但我注意到在第 9 个条目时,哈希图重新散列并使其容量增加了一倍。现在在第 10 次入境时,它的容量再次翻了一番。
谁能解释这是怎么回事?
提前致谢。
【问题讨论】:
-
javadoc 说:当哈希表中的条目数超过负载因子和当前容量的乘积时,哈希表被重新哈希。因此,占用的桶数无关紧要。重要的是条目的数量。
-
好的,谢谢你清除它,但考虑到上面的 hashmap 应该在第 13 个条目调整大小,但它在第 9 和第 10 又做了一次。为什么这样做?
-
您能阅读地图实现的源代码吗?
-
这是一个重现您的实验的类,首先使用 Integers 作为键(行为如文档所示),然后使用 X 作为键(行为“奇怪”):gist.github.com/jnizet/34ca08ba0314c8e857ea9a161c175f13。如果桶太拥挤,HashMap 会变成树,代码说:“最小的表容量,bin 可以被树化。(否则,如果 bin 中有太多节点,表会调整大小。)”。因此,除了记录的内容外,该表还会在存储桶拥挤时自行调整大小,当容量变为 64 时,它会更改为树节点。
-
@JBNizet - 是的,该示例更好地复制了我的案例。是的,似乎一个拥挤的桶正在触发哈希图的双倍容量。您是否有一些来源或参考资料可以进一步解释这种对桶大小的重新散列?
标签: java hashmap load-factor