HashMap

HashMap 1.8 基本数据结构 数组+链表+红黑树
对键值进行计算算出hash值,然后用hash值对数组取模,然后就回定位道数组的一个元素中,然后就可以把数据插入对应的位置。
Jdk1.8对hash算法和寻址优化
 
hash算法优化
将hash值右移16位然后与原本的hash值进行异或---hash值的高16位与低16位进行异或,高低位都可以参与运算
 
寻址算法优化
(n-1)&hash-> 数组的位置
与运算的与取模运算的效果一样,但是与运算的性能比较高
Hash 值 0010 0001 0001 0000 1111 1110 1110 1111
Hash值右移16位 0000 0000 0000 0000 0010 0001 0001 0000
异或运算后 0010 0001 0001 0000 1101 1111 1111 1111
然后数组为长度16(n-1) 0000 0000 0000 0000 0000 0000 0000 1111
与运算得到结果 0000 0000 0000 0000 0000 0000 0000 1111
得到数组第七个位置 让hash 值的高位和地位都参加与与运算 避免有些hash值的低16位都比较相近时,大量的值被定位到一个位置
0000 0000 0000 0000 0000 0000 0111
 
Hash算法优化 对每个hash值,在他的低16中包含了高低16位特征,尽量避免了一些hash冲突。
寻址算法优化:用与运算取代取模,提升性能
 
 
如何解决hash冲突 链表+红黑树 O(n) 和O(long)
如果大量的值定位到了一个数组位置 会在当前的位置生成一个链表 或者红黑树
如果链表很长会进化成红黑树,
当数组长度小于64的时候链表长度大于8时会优先 进行扩容 ,反之会进行链表转化红黑树。
 
Hashmap扩容
2倍扩容
16位的数组 ->32位数组
扩容时会重新进行与运算
原来的hash值 0010 0001 0001 0000 1101 1111 1111 1111
然后32-1 0000 0000 0000 0000 0000 0000 0001 1111
运算后得到位子 0000 0000 0000 0000 0000 0000 0001 1111 位置为 31 为oldindex+扩容大小*
判断二进制的结果中是否多出来一个bit如果没有那就还在原来的index位置,如果多出来了 那么就是index+oldcap,通过这个方式就避免了rehash对数组的取模,取模的性能不高,位运算的性能比较高。

posted @ 2021-03-14 09:40  回忆漫长  阅读(44)  评论(0编辑  收藏  举报