为什么HashMap的长度一定是2的次幂?

HashMap是面试过程中最常问的知识点之一

今天用最通俗易懂的大白话来讲一讲:为什么HashMap的长度一定是2的次幂?

大家知道HashMap中,如果想存入数据,首先它需要根据key的哈希值去定位落入哪个桶中

HashMap的做法,我总结的是,三步:>>>无符号右移、^异或、&与

具体是:拿着key的哈希值,先“>>>”无符号右移16位,然后“^”异或上key的哈希值,得到一个值,再拿着这个值去“&”上数组长度减一

最后得出一个数(如果数组长度是15的话,那这个数就是一个0-15之间的一个数),这个数就是得出的数组脚标位置,也就是存入的桶的位置。

由上边可以知道,定位桶的位置最后需要做一个 “&” 与运算,&完了得出一个数,就是桶的位置

知道了这些以后,再来说为什么HashMap的长度之所以一定是2的次幂?

按照我的理解,至少有以下两个原因:

1、HashMap的长度是2的次幂的话,可以让数据更散列更均匀的分布,更充分的利用数组的空间

怎么理解呢?下面举例子说一下如果不是2的次幂的数的话
假设数组长度是一个奇数,那参与最后的&运算的肯定就是偶数,那偶数的话,
它二进制的最后一个低位肯定是0,0做完&运算得到的肯定也是0,那意味着&完后得到的数的最低位一定是0
最低位一定是0的话,那说明一定是一个偶数,换句话说就是:&完得到的数一定是一个偶数,
所以&完获取到的脚标永远是偶数位,那意味着奇数位的脚标永远都没值,有一半的空间是浪费的
奇数说完了,来说一下偶数,假设数组长度是一个偶数,比如6,那参与&运算的就是5
5的二进制   00000000 00000000 00000000 00000101
发现任何一个数&上5,倒数第二低位永远是0,
那就意味着&完以后,最起码肯定得不出2或者3(这点刚开始不好理解,但是好好想一下就能明白)
意味着第二和第三脚标位肯定不会有值

虽然偶数的话,不会像奇数那么夸张会有一半的脚标位得不到,但是也总会有一些脚标位得不到的。所以不是2的次幂的话,不管是奇数还是偶数,就肯定注定了某些脚标位永远是没有值的,而某些脚标位永远是没有值的,就意味着浪费空间,会让数据散列的不充分,这对HashMap来说绝对是个灾难!

2、HashMap的长度一定是2的次幂,还有另外一个原因,那就是在扩容迁移的时候不需要再重新通过哈希
定位新的位置了。扩容后,元素新的位置,要么在原脚标位,要么在原脚标位+扩容长度这么一个位置

比如扩容前长度是8,扩容后长度是16

第一种情况:
扩容前:
 00000000 00000000 00000000 00000101
&00000000 00000000 00000000 00000111     8-1=7
-------------------------------------
                                 101   ===== 5 原来脚标位是5

扩容后:                       
 00000000 00000000 00000000 00000101
&00000000 00000000 00000000 00001111    16-1=15
-------------------------------------
                                 101   ===== 5 扩容后脚标位是5(原脚标位)


第二种情况:
扩容前:
 00000000 00000000 00000000 00001101
&00000000 00000000 00000000 00000111     8-1=7
-------------------------------------
                                 101   ===== 5 原来脚标位是5
                            
扩容后:                            
 00000000 00000000 00000000 00001101
&00000000 00000000 00000000 00001111    16-1=15
-------------------------------------
                                1101   ===== 13 扩容后脚标位是13(原脚标位+扩容长度)


                            

下面是对应的图解:

为什么HashMap的长度一定是2的次幂?_第1张图片

扩容后到底是在原来位置还是在原脚标位+扩容长度的位置,主要是看新扩容最左边一个1对应的上方数字是0还是1
如果是0则扩容后在原来位置,如果是1则扩容后在原脚标位+扩容长度的位置
HashMap源码里扩容也是这么做的

以上就是对为什么HashMap的长度一定是2的次幂的一些理解

铁子们,如果觉得文章对你有所帮助,可以点关注,点赞

也可以关注下公众号:扫码或 wx搜索:“聊5毛钱的java”,欢迎一起学习交流,关注公众号可领取博主的Java学习视频+资料,保证都是干货

为什么HashMap的长度一定是2的次幂?_第2张图片

3Q~

纯手敲原创不易,如果觉得对你有帮助,可以打赏支持一下,哈哈,感谢~

为什么HashMap的长度一定是2的次幂?_第3张图片           为什么HashMap的长度一定是2的次幂?_第4张图片

你可能感兴趣的:(笔记,Java开发总结,java,hashmap)