对于HashMap的长度必须是2^n的总结

一:为什么HashMap的长度必须是2^n?

首先,如果想要元素散列在一个长度之内,可以直接使用模运算,使用取余数的方法。但是如果想要提高计算机的运算效率,可以使用位运算。通过对 “长度”-1 进行与运算,一样可以达到散列的效果,从而把元素散列在固定长度之内。但是该“长度”必须要满足一个条件,而该条件就是我们的2^n。

二:为什么符合2^n就可以达到散列效果?

首先,我们需要了解2^n的二进制结构:最高位是1,其余为都是0,如2^3 = 1000;

那么(2^n) - 1 实际就是1000-0001 = 111,也就是说(2^n) - 1 的二进制结构是n个1(该特点是下面所有规律的基础!!!)

1.第一种情况:当i<=(2^n) - 1,则(2^n) - 1&i=i。因为随便一个位置上无论是0还是1,只要&1,则还是自己,而(2^n) - 1二进制结构是n个1,所以(2^n) - 1&i=i。比如3&7 = 011&111 = 001;

2.第二种情况当i>(2^n) - 1时,实际i中高于(2^n) - 1最高位之后的数是不用看的,比如9&7,即1001&0111,9的最高位其实是不用看的,因为无论是0与1,与上0后都是0.也就相当于001&111,那么就转化为情况1了。

因此:对一个满足(2^n) - 1的数做与运算,就可以达到散列的效果。那么问题又来了,为什么不直接把容量设定成(2^n) - 1,而是2^n呢?因为长度为2^n,对map扩容移动元素也有很大的效率提升

三:长度为2^n如何提升对map扩容移动元素的效率?(默认大小是16,每一次扩容为原来的2倍)

首先下个结论:

1.如果key的最高位是1,新位置 = 原来的位置+原来数组的长度

2.如果key的最高位是0,新位置 = 原来的位置

为什么?

首先扩容的大小是原来的两倍,具体到二进制就是最高位左移了一位。如1000扩容2倍后就会变成10000,而扩容后对应的(2^n) - 1实际就是比原来多了一个1,如为扩容前是111,扩容后就是1111

(1)那么原来的key如果最高位是1,就相当于多了2^(n-1),而2^(n-1)不就是扩容前map的长度吗?比如9&7 = 1001&0111 = 0001;扩容后,就变成了1001&1111 = 1001,也就是多了最高位的1(可以理解为一张试卷太简单,限制了学霸的发挥,拉不开差距,换个区分度更高的题目,学霸就起飞了);

(2)如果原来的key最高位是0时,比如3&7 = 011&111 = 011;扩容后变成0011&1111 = 0011,即没变(可以理解为即使换了一张试卷,对于学渣来说,还是没有什么变化呀!不会的题还是不会做!)

 其实原理还是因为扩容后最高位是1,即原来的数最高位是什么,该最高位与上1还是他自己

 因此:如果直接让长度为(2^n)-1,如果保证扩容后依然满足(2^n)-1?办法当然有,但是还不如直接让长度为2^n来得方便且高效些

简而言之:HashMap的长度为2^n的原因有二:一是为了实现元素的散列;二是为了HashMap扩容后,更方便地计算出原有元素扩容后的位置

最后:附上后端技术交流圈,欢迎各位大佬入圈交流技术......V:ff1341658(先添加好友后拉群,添加好友时请备注:小白不黑)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值