美文网首页
JDK1.7某些版本HashMap中size超阈值得情况

JDK1.7某些版本HashMap中size超阈值得情况

作者: 山东大葱哥 | 来源:发表于2020-01-21 12:34 被阅读0次

问题

JDK1.7中一个HashMap中是否会出现size>threshold情况?
我这里使用的是jdk1.7.0_67版本。

背景知识

了解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 的阈值。

说明

经网友提醒该算法与jdk小版本有关,在jdk1.7.0_8中该逻辑已变更位如下

voidaddEntry(inthash,Kkey,Vvalue,intbucketIndex){
//获取指定bucketIndex索引处的Entry
Entry<K,V>e=table[bucketIndex];
//将新创建的Entry放入bucketIndex索引处,并让新的Entry指向原来的Entry
table[bucketIndex]=newEntry<K,V>(hash,key,value,e);
//如果Map中的key-value对的数量超过了极限
if(size++>=threshold)
//把table对象的长度扩充到原来的2倍。
resize(2*table.length);
}

相关文章

网友评论

      本文标题:JDK1.7某些版本HashMap中size超阈值得情况

      本文链接:https://www.haomeiwen.com/subject/xnkezctx.html