HashMap中如何计算数组索引下标?

计算hash值的方法

对于key的hashCode做hash操作,无符号右移16位然后做异或运算。
还有平方取中法,伪随机数法和取余数法。这三种效率都比较低。而无符号右移16位异或运算效率是最高的。
集合中的初始化容量(必须是二的n次幂)

//默认的初始容量是16 -- 1<<4相当于1*2的4次方---1*16
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;   

HashMap中如何计算数组索引下标?

hash值与数组长度减一做按位与运算得到数组下标索引

问题: 为什么必须是2的n次幂?如果输入值不是2的幂比如10会怎么样?

举例分析:
说明:按位与运算:相同的二进制数位上,都是1的时候,结果为1,否则为零。

例如长度为8时候,3&(8-1)=3 2&(8-1)=2 ,不同位置上,不碰撞;

例如长度length为8时候,823次幂。二进制是:1000
length-1 二进制运算:
	1000
-	   1
---------------------
     111
如下所示:
hash&(length-1)
3   &(8    - 1)=3  
	00000011  3 hash
&   00000111  7 length-1
---------------------
	00000011-----3 数组下标
	
hash&(length-1)
2 &  (8 -    1) = 2  
	00000010  2 hash
&   00000111  7 length-1
---------------------
	00000010-----2  数组下标
说明:上述计算结果是不同位置上,不碰撞;

例如长度为9时候,3&(9-1)=0 2&(9-1)=0 ,都在0上,碰撞了;

例如长度为9时候,3&(9-1)=0  2&(9-1)=0 ,都在0上,碰撞了;
例如长度length为9时候,9不是2的n次幂。二进制是:00001001
length-1 二进制运算:
	1001
-	   1
---------------------
    1000
如下所示:
hash&(length-1)
3   &(9    - 1)=0  
	00000011  3 hash
&   00001000  8 length-1 
---------------------
	00000000-----0  数组下标
	
hash&(length-1)
2 &  (9 -    1) = 2  
	00000010 2 hash
&   00001000 8 length-1 
---------------------
	00000000-----0  数组下标
说明:上述计算结果都在0上,碰撞了;

总结:

  1. 由上面可以看出,当我们根据key的hash确定其在数组的位置时,如果n为2的幂次方,可以保证数据的均匀插入,如果n不是2的幂次方,可能数组的一些位置永远不会插入数据,浪费数组的空间,加大hash冲突
  2. 另一方面,一般我们可能会想通过 % 求余来确定位置,这样也可以,只不过性能不如 & 运算。而且当n是2的幂次方时:hash & (length - 1) == hash % length
  3. 因此,HashMap 容量为2次幂的原因,就是为了数据的的均匀分布,减少hash冲突,毕竟hash冲突越大,代表数组中一个链的长度越大,这样的话会降低hashmap的性能
  4. 如果创建HashMap对象时,输入的数组长度是10,不是2的幂,HashMap通过一通位移运算和或运算得到的肯定是2的幂次数,并且是离那个数最近的数字。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值