一线大厂面试真题——HashMap啥时候扩容,为什么扩容

概述

这是一个针对1到3年左右Java开发人员的面试题,

问题本身不是很难,但是对于这个阶段来说,由于不怎么关注,所以会难住一部分同学。

分析

存储容器的设计

在任何语言中,们希望在内存中临时存放一些数据,可以用一些官方封装好的集合(如图),比如:List、HashMap、Set等等。作为数据存储的容器。

容器的大小

当们创建一个集合对象的时候,实际上就是在内存中一次性申请一块内存空间。而这个内存空间大小是在创建集合对象的时候指定的。

比如List的默认大小是10、HashMap的默认大小是16。

长度不够怎么办

在实际开发中,们需要存储的数据量往往大于存储容器的大小。

针对这种情况,通常的做法就是扩容。

当集合的存储容量达到某个阈值的时候,集合就会进行动态扩容,从而更好的满足更多数据的存储。

(如图)List和HashMap,本质上都是一个数组结构,所以基本上只需要新建一个更长的数组,然后把原来数组中的数据拷贝到新数组就行了。

以HashMap为例,它是什么时候触发扩容以及扩容的原理是什么呢?

HashMap是如何扩容的

当HashMap中元素个数超过临界值时会自动触发扩容,这个临界值有一个计算公式。threashold=loadFactor*capacity

loadFactor的默认值是0.75,capacity的默认值是16,也就是元素个数达到12的时候触发扩容。

扩容后的大小是原来的2倍

由于动态扩容机制的存在,所以们在实际应用中,需要注意在集合初始化的时候明确指定集合的大小。

避免频繁扩容带来性能上的影响

假设们要向HashMap中存储1024个元素,如果按照默认值16,随着元素的不断增加,会造成7次扩容。

而这7次扩容需要重新创建Hash表,并且进行数据迁移,对性能影响非常大。

最后,可能有些面试官会继续问,为什么扩容因子是0.75?

为什么扩容因子是0.75

扩容因子表示Hash表中元素的填充程度,扩容因子的值越大,那么触发扩容的元素个数更多,虽然空间利用率比较高,但是hash冲突的概率会增加。

扩容因子的值越小,触发扩容的元素个数就越少,也意味着hash冲突的概率减少,但是对内存空间的浪费就比较多,而且还会增加扩容的频率。

因此,扩容因子的值的设置,本质上就是在冲突的概率以及空间利用率之间的平衡。

0.75这个值的来源和统计学里面的泊松分布有关。

(如图)我们知道,HashMap里面采用链式寻址法来解决hash冲突问题,为了避免链表过长带来时间复杂度的增加,所以链表长度大于等于7的时候,就会转化为红黑树,提升检索效率。

当扩容因子在0.75的时候,链表长度达到8的可能性几乎为0,也就是比较好的达到了空间成本和时间成本的平衡。

回答

当HashMap元素个数达到扩容阈值,默认是12的时候,会触发扩容。

默认扩容的大小是原来数组长度的2倍,HashMap的最大容量是Integer.MAX_VALUE,也就是2的31次方-1。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值