HashMap面试

HashMap使用2的幂次方作为数组长度,是因为这样可以通过位运算优化索引计算,确保数据均匀分布且避免空间浪费。非2的幂次方会导致某些数组下标无法被利用。在哈希冲突时,2的幂次方能保证每个位置都有可能存储数据。
摘要由CSDN通过智能技术生成

hashMap数组长度为什么为2的幂次方

我们都知道hashmap是key value类型的结构,它是用数组+链表/红黑树这种方式来存储内容,我们通常开始的时候没有给他设定长度,源码内部对它默认长度的定义是1 << 4 (1左移四位,即10000,表示2的四次幂16),这样的表达方式主要是提醒我们如果我们要自定义hashmap初始长度的话最好将它定义为2的整数次幂。那么HashMapch长度为什么要为2的整数次幂呢?

定义完hashmap默认长度之后,内部是存在一个对应长度数组,我们希望HashMap的值均匀分布在数组每一个下标之上,例如我们定义了一个长度16,我们可以用当前是HashMap存入的第几个值,用这个数字除以16进行取余,来判断将它放到数组哪个下标之上,但是这样我们需要记录当是第多个少值,还要进行一次取余运算,这样占用资源并且还要进行一次取余运算,很是麻烦。

HashMap采用的是"&"运算来计算下标位置,例如我们使用默认长度的1<<4(16)来进行值存储,数组长度为16,则下标为0-15,16的2进制为10000,16-1=15,15的二进制则为1111,HashMap对数组长度1111之前的内容补0,将长度补齐至与key的hash值的二进制相等的长度,&运算的结果,是只有两个都为1的场景(即1&1)才为1,所以1111之前补充的0的&运算结果一直为0,我们可以不做考虑,长度15场景下我们只需要考虑后四位二进制值与key的hash值的后四位即可,例如hash值后四位为1001,将1111与1001进行与运算,的结果为1001(9),则这个key,value存放在数组下标为9的位置上,由于长度为1111,1111进行与运算的最大值为1111,也不会出现数组下标越界的情况,并且每一个位置都可以与运算出0,1,完美解决了hashMap值存放的问题。

明白HashMap值存放原理之后我们再来看为什么n为2的幂次方,2的幂次方2进制值特点为起始为1,后面全0,进行减1操作之后,变为全1的二进制,全一的二进制,可以保证二进制的与运算,每一个位置都可以出现1,保证hashmap数组各个下标都可以分配到值,如果不是2的幂次方的话,减1之后二进制数据会出现0,导致数组下标某些位置一直无法存放到数据,造成空间浪费。例如我们初始化长度定义为17,17的二进制值为10001,减一之后为10000,10000的二进制值进行与运算的时候只会出现10000(16),00000(0)两个值,导致HashMap的值只会存放在下标为0或者下标为16的地方,别的地方不会存储,不满足我们开始的诉求,值均匀的分布在数组每一个下标之上。

回答: HashMapJava中的一个常用数据结构,它的底层是由hash数组和单向链表实现的。每个数组元素都是一个链表,通过Node内部类实现了Map.Entry接口来存储键值对。HashMap通过put和get方法来存储和获取数据。\[1\] 在重写equals方法,我们需要同重写hashCode方法。这是因为在HashMap中,查找value是通过key的hashCode来进行的。当找到对应的hashCode后,会使用equals方法来比较传入的对象和HashMap中的key对象是否相同。因此,为了保证正确的查找和比较,我们需要同重写equals和hashCode方法。\[2\]\[3\] HashMap在什么候进行扩容呢?当HashMap中的元素数量超过了负载因子(默认为0.75)与当前容量的乘积,就会进行扩容。扩容是为了保持HashMap的性能,因为当元素数量过多,链表的长度会变长,查找效率会下降。扩容的过程是创建一个新的数组,将原数组中的元素重新分配到新数组中,然后将新数组替换为原数组。\[3\] #### 引用[.reference_title] - *1* *2* *3* [史上最全Hashmap面试总结,51道附带答案,持续更新中...](https://blog.csdn.net/androidstarjack/article/details/124507171)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值