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

由此产生了死链

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值