JDK1.7的HashMap的环形链表

分析扩容的核心代码

java 复制代码
// 构建新数组
Entry[] newTable = new Entry[newCapacity];
// 迁移老数组数据到新数组
transfer(newTable, initHashSeedAsNeeded(newCapacity));
// 迁移完毕后,替换老数组
table = newTable;
java 复制代码
// 迁移数据的过程
void transfer(Entry[] newTable, boolean rehash){
    int newCapacity = newTable.length;
    // 外层遍历数组
    for (Entry<k,v> e:table){
        // 遍历链表
        // 2号线程走完第二次循环,完成迁移数据(如下图2所示)
        // 1号线程走完第二次循环,发现指向的是A(如下图3所示)
        // 1号线程走完第三次循环,完成迁移数据(如下图4所示)
        while(null != e){
            Entry<K,V> next = e.next;
            // 1号线程执行到这里停止
            if(rehash){
                e.hash = null == e.key ? 0 : hash(e.key)
            }
            int i = indexFor(e.hash, newCapacity);
            e.next = newTable[i];
            newTable[i] = e;
            e = next;
        }
    }
}

图1
图2
图3
图4

JDK1.7中的HashMap是线程不安全的,可能会出现并发扩容的操作。

JDK1.7中的HashMap在迁移数据时,采用的是头插法,导致节点的next指针会有变化。

先迁移完的线程,可能会导致其他线程在扩容时,扩容到最后,将最开始的节点重新的插入到了头节点的位置,导致指针再次变化,从而形成了一个环形链表。

相关推荐
小羊没烦恼!12 小时前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
倒头就睡的小比特12 小时前
算法竞赛C++常用的STL
c++·算法
俊昭喜喜里12 小时前
java中的继承和多态的区别
java
小羊没烦恼!12 小时前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
譕痕12 小时前
JSONObject与JSONArray封装数据格式区别
java·json
胡写代码13 小时前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖13 小时前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商
此时不提桶,更待何时13 小时前
01-06-A-JVM排查实战详解
java·jvm
猎头南楼13 小时前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
vipxieliang13 小时前
ValidX 在 DDD 领域驱动设计中的实践
java·spring boot