HashMap源码深入解析【上】

HashMap的put方法深入解析【上】

在这里插入图片描述
判断table数组是否为空,为空就调用inflateTable(threshold)threshold=capacity*loadfactor即容量乘以负载因子
查看inflateTable(threshold)
在这里插入图片描述
capacity=roundupToPowerof2(toSize),roundupToPowerof2(toSize)的功能是取toSize的最小的2幂次方的一个数
比如:toSize=10,那么capacity=16,(为什么要是2的幂次方呢,这个下面会解释)
有的时候面试的时候也会问,为什么数组的长度是2的整数倍
下面就是创建一个新的Entry的数组table了
查看roundUpToPowerof2(toSize):在这里插入图片描述
我们看到number一开始是进行和最大容量(2^30)进行比较,
当number>1时,就调用了Integer.highestOneBit((number-)<<1)
查看Integer.highestOneBit((number-1)<<1)
在这里插入图片描述
这个方法的作用就是找比i小的最大的2的幂次方:
假如我们的i是10;那么比10小的最大的2的幂次方是8,怎么求呢?
10:0000 1010
8: 0000 1000
首先:i右移1位得到:
0000 0101
然后或运算:
0000 1010
0000 0101
0000 1111
此时的i为0000 1111
然后:i右移2为
0000 0011
或运算:
0000 0011
0000 1111
0000 1111
此时i还是000 1111

因为是异运算,最后i还是0000 1111
最后return i-(i>>>1)
i>>>1是无符号有意变成了
0000 0111
即结果为:
0000 1111- 0000 0111=0000 1000(十进制就是8),
为什么i|=(i>>16),因为传过来的值是int类型的,int类型是32位
有的人会问,roundupToPowerof2(toSize)是取大于toSize得最小2得幂次方,但是调用得Integer.highestOneBit(int i),是获取比i小得最大幂次方不就是矛盾了吗?
让我们仔细看看这个Integer.highestOneBit((number-1)<<1)得参数,number是先左移,假设number=10,10-1=9,9在左移变成18,比18小得最大得2得幂次方不就是16吗,即roundupToPowerof2(10)不就是16吗。
有得人会问,为什么要减1呢?
假如我们得number是8,正好是2得幂次方,但是如果不减1那么number<<1就变成了16.Integer.highestOneBit(16),还是16,追溯其上,那么capacity=16,减去1这个Integer.highestOneBit(14),返回的值还是8.
在这里插入图片描述
下面我们开始从int hash=hash(key):,求key得hash
查看hash(key)
在这里插入图片描述
我们可能迷惑得点是为什么

h=key.hashCode()^(h>>>16):

h>>>16是取hashCode的高16位(因为h右移,高16位补0,低16位移除)
我们先看下面得int i=indexFor(hash,table.length),i是table数组得下标
在这里插入图片描述

比如:
length为15:0000 1111
hashCode: 1010 1010
相与得到得结果就是:
0000 1010
我们发现hashCode的前4位是几不重要,没有体现什么价值,
所以为了更加散列,我们需要利用hashCode的高位,为什么是h>>>16呢,但由于绝大多数情况下length一般都小于2^16即小于65536。
现在我们来解释为什么h要与length相与还要减1呢
假如我们table数组的长度是16,那么我呢要确保我们的数组下标要在0-15之间
长度 16:0001 0000
15:0000 1111
hashCode: 1010 1010
hashCode和15进行相与得:0000 1010
因为15是有规律得,低4位都是1,那么得到得结果就是0-15之间
假如我们拿16与hashCode相与得到:0000 0000:不符合
所以我们反推就是taoble长度必须是2得幂次方,比如:32-1=31:0001 1111,低五位都是1这样与HashCode相与出来得范围才是0-31;满足我们得数组下标

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值