九成的人会答错的HashMap阈值问题
2019-06-28 本文已影响27人
山东大葱哥
问题
JDK1.7中一个HashMap中是否会出现size>threshold情况?
背景知识
了解HashMap的同学都知道,HashMap中有几个重要的字段:
- 负载因子loadFactor,指哈希表在其容量自动增加之前可以达到多满的一种尺度
- 容量 capacity ,也就是当前table数组的长度
- 阈值threshold,用于判断是否需要调整HashMap的容量(rehashing),阈值=capacity * load factor
- 大小size,即HashMap存储的键值对数量
HashMap扩容的条件
关于扩容条件很多资料说的都是在size超过阈值时,就会触发扩容,以减少冲突的发生。
但我在这里告诉大家,这个说法是错误的或者是不准确的。我们直接看jdk1.7中HashMap的源代码:
void addEntry(int hash, K key, V value, int bucketIndex) {
//判断已经存在的Entry数量是否超过了实际可容纳量、当前节点是否发生hash碰撞。
if ((size >= threshold) && (null != table[bucketIndex])) {
//如果超过阈值并且即将发生hash碰撞,则进行resize
resize(2 * table.length);
//重新计算hash
hash = (null != key) ? hash(key) : 0;
//重新计算索引位置
bucketIndex = indexFor(hash, table.length);
}
//创建Entry节点对象
createEntry(hash, key, value, bucketIndex);
}
看到其中的if条件是,与,两个条件都满足才进行resize:
- size大于等于阈值
- 当前节点发生hash碰撞
所以如果只是size超过了阈值,而当前节点不发生碰撞的话,还是可以继续在原数组中存储数据的,因此就会出现下图的情况:
image.png
size=14 超过了 threshold=12 的阈值。