HashMap的初始容量的处理方案
HashMap的初始容量的处理方案
总所周知HashMap的默认的初始容量是16,当然HashMap也支持自定义一个初始容量,那么我们定义的初始容量到底会经过哪些处理呢?
首先我们自定义一个初始容量,HashMap的构造方法会调用一个tableSizeFor的一个方法,我们再发现,里面调用的是Integer中的highestOneBit中的方法,我们先看这个方法到底有什么用处呢?
我这里先写一个小demo看一下效果
首先我们先看一下代码实现的效果,然后在进行分析
Integer中的highestOneBit中的方法怎么判断传进去的一数字得出来的结果是小于等于这个数字的二次方数
首先我们先看jdk内部的这个方法的实现
内部的实现的方法
public static int highestOneBit(int i){
i |= (i<<1);
i |= (i<<2);
i |= (i<<4);
i |= (i<<8);
i |= (i<<16);
return i - (i >>>1);
}
我们先以10这个数字进行演示计算机底层的实现
计算机怎么这个10 ? 2 次方
这里有两个关键的是右移运算和或运算
10这个数字进行二进制转换后是
0000 1010 这是10的二进制表达出来的
第一行代码的第一步:
0000 0101
也就是进行第一次运算右移一位前面补充一个0,剩下的进行位移。将后面的0给挤掉,
第一行代码的第二步:
0000 1111
也就是四个数字,有1则全部都是1,前面四位全是0,所以进行|运算之后还是0,后面是0101,其中有两个1,当计算机进行|运算碰到第一个1的时候,会把整个四位全部变成1,结果就是0000 1111
第二行代码的第一步:现在位移的是两位,上面位移的是1位上面得到的结果就是0000 1111现在开始对这个数值进行计算
0000 0011,前面补充两个0,后面的两个1给挤掉,所以出来的结果就是0000 0011
第二行代码的第二步:
0000 1111
然后重复上面步骤进行再次运算得出来的结果就是这样的
再次进行|运算得出来的结果还是和上面第一行代码的第二步的结果是一样的,也是0000 1111
开始看return里面的运算
这个i也就是10,再次位移1位也就是
0000 0111
这个数字得出来的结果进行i-(i>>>1)运算得出来的结果就是0000 1000 这个数字再进行二进制转10进制的出来的结果,
0000 1000 ---------> 8
所以得出来的结果就是我们想要的结果,这就是当传进去的一个数字,会获得小于等于这个数字的二次方数
现在代表很多数字,基于这个数字再运算一次
0001 ****
0000 1***再次和上面的数字这两个数字进行|运算,两个数字,有1就是1,
0001 1***得出来的结果就是这样的,后面的*是随意数字
上面的步骤实现的是第一行代码;
然后在进行位移2位得出来的结果是
0000 011* 这是位移出来的结果
然后在再将上面的两个数字进行|运算 0001 1*** 和 0000 011* 得出来的结果就是0001 111*
在这里发现一个规律就是慢慢的将上面的后面四位数字全部变成1
既然这样为什么还要进行位移4,8,16呢?
这里我们传进去的是int类型,在java中int类型的基本数字类型占用的内存空间是4个字节 每个字节8位 4*8 是32位
然后在进行两个数字相减 0001 1111 - 0000 1111 得出来的效果是 0001 0000 这样获取出来的二进制就是我们想要的结果,就是2的次方数
然后再回到HashMap中
private static int roundUpToPowerOf(int number){
return number >= MXIMUM_CAPACITY ? MAXIMUM_CAPACITY : (number >1) ? Interger.highestOneBit((number - 1)<<1) : 1;
}
在想一下,当我们传进去的一个数字是10,那么我们的HashMap的初始容量到底是多少,既然调用的是Integer中的方法,如果不做处理,那么我们的HashMap中的
初始容量就是8,但是其实不是的,传进去的是10,我们想要的是16,HashMap中的代码是如何进行运算的呢?
我们应该把10变大,怎么变大?需要变大的范围必须是大于16但是必须是小于32,我们应该怎么控制这个范围呢?
首先我们通过位移运算,
10用十进制表示的是:
0000 1010
0001 0100进行左移动后的数字 这样得出来的二进制,再转换成十进制就是20
20正好就是在16和32之间数字。
通过调用Integer中的方法,运算,最后我们通过上面这些运算,我们发现,最后得出来的结果就是0001 0000,这个数字就是16;
分析到这里,只能感叹,java的开发者对于任何运算已经到了出神入化的地步,是我可望不可即的大人物。
本文地址:https://blog.csdn.net/admin447/article/details/108032568
上一篇: JDBC连接数据库登录·(一)
下一篇: SFTP Java协议应用