HashMap源码(七)----核心原理总结

1、hash算法为何要高16位和低16位做异或运算?

  后续环节的位运算用的是低16位,如果不把hashcode值的高16和低16位进行运算,就会导致后面通过hash值找数组的index时,只有低16位参与了运算。有了该异或运算,在hash值的低16位里面,同时保留了高16位和低16位的特征。定位index时,可以降低hash冲突的概率,减少hash冲突。

2、为何定位时将hash值和数组.length - 1与运算?

  当数组长度n为2的整数次幂时,hash值与(n-1)运算的结果相当于取模,但是效率比取模高。

3、为何每次扩容都要2的n次幂

  这是现在hashmap优化后的效果。数组刚开始的初始值,以及每次扩容的值,都是2的n次方,16、32、64。因为只要满足这个条件,就可以保证,一个数对(n - 1) 做与运算,和其对n取模效果一样。

4、hash冲突的机制

  在jdk1.7之前都是用链表来解决,在jdk1.8之后引入了红黑树。但是在jdk1.8,也是先用链表来处理,当链表长度超过8时采用红黑树。

5、扩容机制

1)数组2倍扩容
2)rehash

6、Rehash机制

1)如果index对应的节点是红黑树,调用HashMap$TreeNode的split方法区处理。
2)如果index对应的节点是链表,则遍历链表中每一个节点,对每一个节点的hash值和oldCap做与运算。结果分为0、1两种情况,构成两条链表。然后将这两条链表分别挂载新数组的index和index+oldCap(结果为1时)上。
3)如果即不是链表,也不是数组,则直接将其的hash值与 (newCap - 1)做与运算,定位到index。

put操作的总结

1)对key计算hashcode值
2)对hashcode值无符号右移16位,再与hashcode值做异或运算,得到hash算法结果
3)判断数组是否为空,第1次put时,数组是为空的,这时put前需要初始化一个长度为16(默认)的数组。
4)将hash算法的结果与(n-1)做与运算,定位到数组的某个index
5)判断该index是否为null,如果为null则创建一个节点,放在index这个位置上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值