上面的答案很好,但是我想解释更多为什么Java可以使用size创建索引
例如,我有一个像这样的size(这个测试是在Java7上进行的,我看到Java8改变了HashMap很多,但是我认为这种逻辑仍然非常好)
// Default length of "budget" (table.length) after create is 16 (HashMap#DEFAULT_INITIAL_CAPACITY)
HashMap hashMap = new HashMap<>();
hashMap.put("A",1); // hash("A")=69, indexFor(hash,table.length)=69&(16-1) = 5
hashMap.put("B",2); // hash("B")=70, indexFor(hash,table.length)=70&(16-1) = 6
hashMap.put("P",3); // hash("P")=85, indexFor(hash,table.length)=85&(16-1) = 5
hashMap.put("A",4); // hash("A")=69, indexFor(hash,table.length)=69&(16-1) = 5
hashMap.put("r", 4);// hash("r")=117, indexFor(hash,table.length)=117&(16-1) = 5
您可以看到具有键size的条目索引和具有键size的对象和具有键size的对象具有相同的索引(= 5)。 这是我执行上面的代码后的调试结果

图片中的表格在这里
public class HashMap extends AbstractMap implements Map, Cloneable, Serializable {
transient HashMap.Entry[] table;
...
}
=>我明白了
如果索引不同,新条目将添加到表中
如果索引相同并且size相同,则新值将更新
如果索引相同而size不同,则新条目将指向旧条目(例如size)。 然后您知道为什么table.length具有字段next
static class Entry implements java.util.Map.Entry {
...
HashMap.Entry next;
}
您可以通过阅读size中的代码再次进行验证。
像现在一样,您可以认为size永远不需要更改大小(16),因为size总是返回值<= 15,但它不正确。
如果您查看size代码
if (this.size >= this.threshold ...) {
this.resize(2 * this.table.length);
当size> = size时,size将调整表的大小(双表长度)
什么是size? size计算如下
static final int DEFAULT_INITIAL_CAPACITY = 16;
static final float DEFAULT_LOAD_FACTOR = 0.75F;
...
this.threshold = (int)Math.min((float)capacity * this.loadFactor, 1.07374182E9F); // if capacity(table.length) = 16 => threadhold = 12
什么是size? size计算如下。
当然这里的size不是table.length。
每当您将新条目放置到HashMap和HashMap中时,需要创建新条目(请注意,当键相同时HashMap不会创建新条目,它只是覆盖现有条目的新值),然后size++
void createEntry(int hash, K key, V value, int bucketIndex) {
...
++this.size;
}
希望对你有帮助
本文详细解析了Java HashMap在Java7中如何使用哈希值计算索引,以及在达到特定条件时如何进行扩容。通过示例展示了哈希冲突时的处理方式,并解释了size在HashMap中的作用,包括容量阈值和负载因子的计算。同时,讨论了当新插入的键值对与已有键值对哈希值相同时,HashMap的行为。最后,提到了Java8中HashMap的变化,尽管有所改变,但基本逻辑保持一致。
1429

被折叠的 条评论
为什么被折叠?



