【链表】关于链表结构
关于链表结构
每次看链表结构相关代码就有点晕,还看不明白,得想半天。看下面这篇分析的时候又感觉有点费劲了。
面试官: HashMap 为什么线程不安全?
这个问题以前了解过,时间一长就忘记了。先说结论:
JDK 1.7 HashMap 上的链表结构使用的头插法,并发情况会导致生成环形链表。这样 HashMap 轮循时会在环形链表上陷入死循环。
JDK 1.7 中 transfer 函数:
void transfer(Entry[] newTable, boolean rehash) { int newCapacity = newTable.length; for (Entry<K,V> e : table) { while(null != e) { Entry<K,V> next = e.next; 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; } } }
未 resize 前的数据结构:
- 最开始 hash 表 size=2,key=3,7,5,则都在 table[1] 中。
- 然后进行 resize,使 size 变成 4。
table 遍历的是 3,7,5 链表。
get, set 方法看习惯了,直接获取、设置 next 属性看着还挺别扭。好像是因为这个原因,理解起来有点障碍了。
Entry<K,V> next = e.next;
改写成 e.getNext()
;
e.next = newTable[i];
改写成 e.setNext(newTable[i]);
理解起来就不一样了。
线程A挂起前:
next
已经先赋值为 7,5 链表。newTable[i]
还没有元素,此时e = 3
,所以,e.next = newTable[i]
,即 3 指向了null
。
先记住下面的描述方便理解:
e.next
与next
容易混淆,注意区分,两者是不同的变量。- 后续
newTable[i]
指向的是链表头部,取值也直接取的头部。不涉及遍历的话不用关心链表其它位置的元素。 - 链表 next 后,以 next 元素为头部,取其后的元素为组成的链表。不再包含前面的元素。关联单向链表对象来思考,对象只有 next 属性,没有 pre 属性。所以,会丢失前面的节点信息。
本文作者:JamKing
本文链接:https://www.cnblogs.com/JamKing/p/16733826.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步