HashMap扩容原理

HashMap扩容原理#

在添加元素或初始化的时候需要调用resize方法进行扩容,第一次添加数据初始化数组长度为16,以后每次每次扩容都是达到了扩容阈值(数组长度*0.75)。
每次扩容的时候,都是扩容之前容量的2倍。
扩容之后,会新创建一个数组,需要把老数组中的数据挪动到新的数组中。

  • 没有hash冲突的节点,则直接使用e.hash&(newCap-1)计算新数组的索引位置。
  • 如果是红黑树,走红黑树的添加。
  • 如果是链表,则需要遍历链表,可能需要拆分链表,判断e.hash&oldCap是否为0,该元素的位置要么停留在原始位置,要么移动到原始位置+增加的数组大小这个位置上。

JDK1.7多线程扩容死循环#

在JDK1.7的hashmap中在数组进行扩容的时候,因为链表是头插法,在进行数据迁移的过程中,有可能导致死循环。
比如说,现在有两个线程
线程一:读取到当前的hashmap数据,数据中一个链表,在准备扩容时,线程二介入。
线程二:也读取hashmap,直接进行扩容。因为是头插法,链表的顺序会进行颠倒过来。比如原来的顺序是AB,扩容后的顺序是BA,线程二执行结束。
线程一:继续执行的时候就会出现死循环的问题。
线程一先将A移入新的链表,再将B插入到链头,由于另外一个线程的原因,B的next指向了A,所以B->A->B,形成循环。
当然,JDK8将扩容算法做了调整,不再将元素加入链表头(而是保持与扩容前一样的顺序),尾插法,就避免了JDK1.7中死循环的问题。

posted @   worshipone  阅读(54)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示