本文主要是介绍HashMap的tableSizeFor方法解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
前言
HashMap的源码有点小复杂,一次性没办法全部弄懂,所以分多次去理解,看懂一点就记录一点,最后再来写个汇总篇,这里先记录其中的tableSizeFor方法。另外jdk版本是1.8.
上代码
/*** Returns a power of two size for the given target capacity.*/static final int tableSizeFor(int cap) {int n = cap - 1;n |= n >>> 1;n |= n >>> 2;n |= n >>> 4;n |= n >>> 8;n |= n >>> 16;return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;}
看英文注释大概也知道是什么意思了,返回目标容量对应的2的幂次方大小,举个栗子:
5到8都返回8,9到16都返回16,明白了吧;
那为什么hashMap的数组长度总是要2的幂次方大小呢?
这里简单说下,HashMap在存数据时,是根据key的hash值(实际还做了扰乱处理)与数组长度-1(2的n次幂-1后二进制低位全是1)进行&运算确定数组的位置,全是1能够保证数据均匀分布,如果有一些位置为0,对应的一些数组位置永远都不会有数据,文字面描述的比较抽象,不明白的可以自己动手试一试,这是另外一个话题,这里不多说。
代码解析
找一个数据来走一遍这段代码,例如2^29 + 1,对应的二进制是:00100000000000000000000000000001
第一步:int n = cap - 1;
n:00100000000000000000000000000000
第二步:n |= n >>> 1;
00100000000000000000000000000000
|
00010000000000000000000000000000
=
00110000000000000000000000000000
第三步:n |= n >>> 2;
00110000000000000000000000000000
|
00001100000000000000000000000000
=
00111100000000000000000000000000
第四步:n |= n >>> 4;
00111100000000000000000000000000
|
00000011110000000000000000000000
=
00111111110000000000000000000000
第五步:n |= n >>> 8;
00111111110000000000000000000000
|
00000000001111111100000000000000
=
00111111111111111100000000000000
第六步:n |= n >>> 16;
00111111111111111100000000000000
|
00000000000000000011111111111111
=
00111111111111111111111111111111
第六步:return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
00111111111111111111111111111111
+
00000000000000000000000000000001
=
01000000000000000000000000000000
最终2^29 + 1得到的结果为2^30,符合我们最初的判断。观察数据我们发现其实这一段代码的逻辑分三个部分,先减一,再将得到的数的二进制数从1开始全部变成1,最后再加一,最终得到的数总是2的n次幂;你可以再拿个小数再走一遍流程,会让你更加清晰,我这里就不再做了。
这篇关于HashMap的tableSizeFor方法解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!