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指针会有变化。

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

相关推荐
虚拟世界AI8 分钟前
Java服务器开发:零基础实战指南
java·servlet·tomcat
2501_945424808 分钟前
C++跨平台开发实战
开发语言·c++·算法
m0_672703319 分钟前
上机练习第50天
算法
中科院提名者19 分钟前
莫比乌斯反演(Möbius Inversion)
算法
Tisfy23 分钟前
LeetCode 1727.重新排列后的最大子矩阵:枚举矩形底边是哪一行 + 排序
算法·leetcode·矩阵
码界奇点24 分钟前
基于模块化架构的Unity游戏开发框架设计与实现
java·c++·unity·架构·毕业设计·源代码管理
Via_Neo28 分钟前
日期问题和日期常用API
数据结构·算法
后端AI实验室30 分钟前
同一个需求,我先出技术方案,再让AI出方案——差距让我沉默了
java·ai
xyyaihxl32 分钟前
springboot与springcloud对应版本
java·spring boot·spring cloud
爱滑雪的码农40 分钟前
Java基础五:运算符与循环结构
java·开发语言