HashMap的扩容过程

本文详细解释了JavaHashMap在装载因子达到一定阈值或插入新元素时的扩容机制,包括触发条件、创建新数组、重新哈希、链表/红黑树调整以及垃圾回收等步骤。
摘要由CSDN通过智能技术生成

一:扩容条件

在Java中,HashMap的扩容条件是基于当前HashMap容量(即内部数组的大小)和实际存储元素的数量。具体来说,在Java 7及以后版本中,HashMap扩容的触发条件如下:
1,装载因子阈值: 当HashMap中的元素数量(entry数量)超过当前容量与预设的负载因子(load factor)的乘积时,会触发扩容操作。默认负载因子为0.75,也就是说,当HashMap中的元素个数达到容量的75%时,就会进行扩容。

2,插入新元素时: 在执行put()操作尝试插入一个新的键值对时,如果发现现有元素数量已经达到了扩容阈值,并且确实需要新增一个元素(不是替换已存在的元素),那么也会触发扩容操作。
扩容过程涉及创建一个新的、更大容量的数组,并将原数组中的所有键值对重新计算哈希值并移动到新的数组中。这个过程也称为“rehashing”,并且在Java 8中引入了优化,链表长度大于某个阈值时会转化为红黑树,以减少搜索、插入和删除的时间复杂度。

二:举例说明:

初始容量为16,当添加第13个元素时,HashMap扩容的流程是什么样的

当初始容量为16的HashMap添加第13个元素时,由于默认负载因子是0.75,所以扩容阈值(threshold)计算公式为:capacity * loadFactor = 16 * 0.75 = 12。

因此,当添加第13个元素时,HashMap的实际存储元素数量超过了扩容阈值(即当前已存储12个元素+即将添加的第13个元素),将会触发扩容操作。

扩容流程如下

创建新的Entry数组: HashMap会创建一个新的Entry数组,其容量通常是原来容量的两倍加一,也就是newCapacity = oldCapacity << 1 = 16 * 2 = 32。

重新哈希所有元素: 遍历原HashMap中的每个Entry(键值对),使用新的容量重新计算它们的索引位置,并将这些Entry放入新的数组中。这个过程被称为“rehash”。

链表拆分或树形结构调整: 如果在扩容过程中某个桶(bucket)下形成了链表结构,那么在这个桶下的链表会根据新的索引被拆分成两个链表,分别存放在新数组的相应位置。在Java 8及以上版本中,如果链表长度超过8且HashMap允许转化为红黑树(通过treeifyThreshold控制,默认也是8),则链表会被转换为红黑树。

替换引用: 扩容完成后,HashMap会将内部引用指向新的Entry数组,旧数组将不再使用,随后垃圾回收机制会在适当的时候回收旧数组。

这样就完成了HashMap的扩容操作,之后可以继续安全地添加新的元素,而不会因为超出容量限制导致无法插入。

小提醒:
HashMap初始化之后,并没有立即分配内存空间,初始化时并没有初始化数组 table,在 put 操作时才初始化;

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

见未见过的风景

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值