HashMap和CurrentHashMap(补充知识篇)

1.哈希值怎么求的

key的hashCode值无符号右移16位,然后按位异或,得到hash值。。这样能让结果更加均匀,离散效果更好。

如果hashCode值的高位变化很大,而低位变化很小或没有变化,那么直接和数组长度进行&运算。会很容易造成计算的结果是一样的,导致hash冲突,而>>>16便是使高混乱度地区与低混乱度地区做一个中和,提高低位的随机性,减少哈希冲突

2.下标索引怎么求的?

可以直接   hash值% 数组长度,但是这样速度太慢了。

因为  HashMap里的数组长度永远是 2的幂。

 所以使用  hash值 &(数组长度-1)  按位与 来获得下标索引(比%快几十倍,不用进制转换)。

3.HashMap 的put 简易流程

JDK8 之后,HashMap只会在第一次 put的时候建立hashTable数组(默认为16)。

得到key的hash值,然后算出数组下标索引,找到数组那个位置的节点

  • 若该位置的tableNode为null,则直接插入键值对在这个节点。
  • 该位置的tableNode不为null,先比较这两个key的hash值,若一样,则继续使用 equals()方法 比较key。相等则覆盖该节点的value;不相等,此时出现hash冲突,继续向下和其他的数据key比较,如果都不相等,则划出一个节点存储数据(如果发现这个节点是红黑树的节点,就按红黑树那套插入键值对;不是就按链表那套,但是要判断链表的长度是否超过8,如果超过8,那就把链表转成红黑树)。

4.为什么要在8个节点的时候升级成红黑树?

TreeNodes占用空间是普通Nodes的两倍,所以只有当bin包含足够多的节点时才会转化成TreeNodes

因为树节点的大小大约是普通节点的两倍,所以我们只在箱子包含足够的节点时才使用树节点(参见TREEIFY_THRESHOLD)。
当他们边的太小(由于删除或调整大小)时,就会被转换回普通的桶,在使用分布良好的hashcode时,很少使用树箱。
理想情况下,在随机哈希码下,箱子中节点的频率服从泊松分布
第一个值是:

 * 0:    0.60653066
 * 1:    0.30326533
 * 2:    0.07581633
 * 3:    0.01263606
 * 4:    0.00157952
 * 5:    0.00015795
 * 6:    0.00001316
 * 7:    0.00000094
 * 8:    0.00000006
 * more: less than 1 in ten million

当hashCode离散性很好的时候,树形bin用到的概率非常小,因为数据均匀分布在每个bin中,几乎不会有bin中链表长度会达到阈值。但是在随机hashCode下,离散性可能会变差,然而JDK又不能阻止用户实现这种不好的hash算法,因此就可能导致不均匀的数据分布不过理想情况下随机hashCode算法下所有bin中节点的分布频率会遵循泊松分布,我们可以看到,一个bin中链表长度达到8个元素的概率为0.00000006,几乎是不可能事件,所以之所以选择8,不是随便决定的,而是根据概率统计决定的。

这说明转化为红黑树的概率还是很小的

红黑树的平均查找长度是log(n),如果长度为8,平均查找长度为log(8)=3,链表的平均查找长度为n/2,当长度为8时,
平均查找长度为4,此时才有转换成树的必要,链表长度如果是小于等于6,链表的平均查找长度为6/2=3,而红黑树此
时为log(6)=2.6,虽然速度也很快
但是转化为树结构和生成树的时间并不会太短,两者此时所用时间相差无几

4.1 转换成红黑树,红黑树是怎么旋转的?

5.为什么在计算是否超过扩容阈值的时候加1.0F

比如   数组里正好6个,负载因子为0.75,这个时候新数组大小就为8,但是8这个大小(正好满足负载,下一次put就还要立马再扩,所以不如直接扩到16)。


7.快速计算扩容后,元素的新索引

我们发现当数组长度从16扩容至32,只是多了一个bit位的运算。(即从右往左多看二进制hash值的一位)。因为扩容是原来的 2倍,二进制的n-1   从右往左看,多了一位 1。

  • 如果Hash值的那一位为0,则新索引=原索引(0&1=0),
  • 如果Hash值的那一位为1,则新索引=原长度+原索引。

8. concurentHashmap

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值