HashMap1.7 扩容时产生死链
目录
HashMap1.7 扩容机制
扩容时产生死链
原因
产生过程
HashMap1.7 扩容机制
HashMap1.7 扩容机制:当 put 一个新键值对时;发生了哈希碰撞(hash值相同)并且加上新键值对后,键值对总数达到了阈值(容量 * 0.75)
① 如:容量为 16 的HashMap,每个位置都放了一个键值对;它并不会扩容,因为没有发生哈希碰撞
② 提问:容量为 16 的HashMap,最多可以放多少个键值对?
答:26个
在 0 号位置先加入 11 个键值对(其他位置都可以),然后将剩余空位置填满;结果为 11+15=26;假如再 put 一个新键值对,这时才会发生哈希冲突并且总数达到阈值。
扩容时产生死链
原因
① HashMap1.7 添加元素为头插法
② HashMap 线程不安全,在并发情况下触发了扩容
产生过程
场景:假设有一个已经达到阈值并且再添加一个新键值对就会发生哈希碰撞(触发扩容)的 HashMap,现在有两个线程往里添加新键值对,此时可能会出现死链
如图:
因为 1.7 为头插法;所以下标为 1 的位置,顺序与插入顺序相反。
假设此时:
Thread0 插入 key 的 hash 为 21 的键值对(扩容前在 5,扩容后会放到位置 21)
Thread1 插入 key 的 hash 为 22 的键值对(扩容前在 6,扩容后会放到位置 22)
两个线程的操作都会使 HashMap 扩容,并且假设 HashMap 在 Thread0 时扩容完成。
此时 1,33 还是会在原来的下标位置,转移到新数组执行的操作为:
第一次循环:
e 1
next 33
e.next null
newTable[1] 1 -> null
第二次循环
e 33
next null
e.next 1
newTable[1] 33 -> 1 -> null
Thread0: 33 -> 1 -> null
假设此时 Thread1 已经获取到 e 与 next 的值 并且刚开始迁移
第一次循环(e 与 next 已经发生改变):
e 1 -> null
next 33 -> 1 -> null
e.next null
newTable[1] 1 -> null
第二次循环
e 33
next 1
e.next 1
newTable[1] 33 -> 1 -> null
第三次循环
e 1
next null
e.next 33 -> 1 -> null
newTable[1] 1 -> 33 -> 1 -> null
由此产生了死链
HashMap1.7 扩容时产生死链相关推荐
- programfilesx86可以移动吗_配置全套的移动洗砂机多少钱?时产200吨可以处理吗?...
移动洗砂机是成品砂石清洗常用的一类清洗机械,机械洗砂,让砂子更干净.品质更高,而且生产更g效,是大多数砂石厂的青睐之选,机械洗砂,常被用作制砂机之后,用于完成细碎砂石的清洗筛选作业.移动洗砂机械全套设 ...
- HashMap扩容时的rehash方法中(e.hash oldCap) == 0算法推导
PS:由于文档是我在本地编写好之后再复制过来的,有些文本格式没能完整的体现,故提供下述图片,供大家阅览,以便有更好的阅读体验: HashMap在扩容时,需要先创建一个新数组,然后再将旧数组中的数据转移 ...
- JDK1.7扩容时为什么会产生并发死链问题
问题: 1.JDK1.7为啥为产生并发死链问题 并发,即多线程同时访问HashMap 需要知道的一些前提知识: 1. JDK1.7是采用有插法进行节点的添加的 2. HashMap的扩容长度为原来的一 ...
- Java HashMap1.7头插法扩容时出现循环链表 1.8换成尾插法
HashMap扩容流程 单线程下扩容 多线程下扩容 当前顺序: 用Key值表示键值对,顺序为5->9->11->null 插入节点流程 next=node.next;//存储下一个需 ...
- hashmap扩容时死循环问题
废话不多说,大家都知道,hashmap不能用于多线程场景中,多线程下推荐使用concurrentHashmap! 但为什么多线程下不能使用hashmap那,主要原因就在于其的扩容机制. 文章是综合他人 ...
- C++中vector容器为什么扩容时按照2倍或者1.5倍进行扩容
扩容机制 首先在VS2013底下,vector的扩容操作是每次扩容*1.5:在GCC环境下是2倍. GCC下的扩容方式是以二倍形式扩容. VS2013下是以1.5倍进行扩容 所以可能会有疑问: 问题一 ...
- Hashmap扩容时出现循环链表(jdk1.8把头插法换成了尾插法的原因)
参考:https://blog.csdn.net/sinat_39410753/article/details/106242573 1.容量计算 容量的阈值=容量*加载因子 2.扩容容量 扩容的容量大 ...
- vmware给虚拟机扩容时,扩展按钮是灰色的解决办法
废话不多说,这是因为你的虚拟机有快照,将目前的所有快照删除即可进行扩容 扩容教程可以参考这个文章,亲测有效
- es6模板字符串中标签模板作为参数时产生空元素的问题
当模板字符串作为标签模板使用时,标签函数接受到的参数分别为(arr,-values) arr:模板字符串中所有那些没有变量替换的部分 -values:各个变量替换后的值 即 let a = 'Oh!' ...
最新文章
- html 写一个日志控件 查看log
- 开源化学信息学库 :ScaffoldGraph
- Swift Property Wrapper 属性包装器
- 鲁迅先生就ERP实施问题答记者问
- hdu4975 行列和构造矩阵(dp判断唯一性)
- 【双百解法】剑指 Offer 15. 二进制中1的个数
- 13寸笔记本电脑尺寸_2019年五款最好的13英寸笔记本电脑(windows)
- 打开程序并监听程序是否退出
- Sobel边缘检测算法及OpenCV函数实现
- matlab 2018 ccs,Matlab2018a 与ccs7生成tms320F2812代码调试记录
- 带下拉菜单截图 巧用PrtSc截图键
- KEIL中无IAP或者STC芯片型号怎么办
- MTK G-sensor 1
- JavaScript(JS) date.getMonth()
- RTI DDS. c++11例子 -1
- php eval 引号,PHP手册-eval()(可以将单引号中的变量解析)
- 安装brat的jquery错误
- 什么是 ARPU 为什么你应该关心 ARPU?
- 大数据预测犯罪?不 是预防犯罪!
- postgresql 密码修改,忘记密码进行修改重置
热门文章
- 关于图像处理分析的一些理解
- 一起打造自己的自动驾驶小车mycar - 4.手柄控制小车移动
- 数组 保存学生的成绩
- GateWay网关访问服务出现503的问题解决
- 初识Ethernet(以太网)和Token Ring(令牌环网)的区别
- 认识Android应用开发(一)
- 面试官:IoC 和 DI 有什么区别?
- usleep()和sleep()的区别
- 关于.aspx与.aspx.cs的关系
- Gitte (https://gitee.com/) 常用git指令--实例