HashMap解析
2021-04-05 本文已影响0人
Raven
什么是HashMap
采用数组+链表的结构来实现,允许空KV,非线程安全。
初始参数
- 初始大小16
(大小必定为2的幂数,计算下标的算法为hash&size-1;2的幂数减一的值二进制下所有位数都为1,这样就保证了下标的值为hash的后几位,只要hash本身分布均匀,计算下标的算法就是相对均匀的,使得数据能够均匀分布到数组中)
- 负载因子0.75
(空间利用率与时间复杂度之间的取舍)
赋值操作
添加元素时,根据key的hashcode再hash(根据key的hashcode与hashcode的高16位的hashcode做异或操作得到,加大低位的随机性,保证了hashcode的32位值,只要有一位发生变化,整个hash值就会发生改变)
,然后根据这个hash值结合数组长度,定位到下标,将key与value包装成Entry(1.8为Node类)
,放入下标中。如果发生冲突的话,以头插法(1.8为尾插法,头插法在并发扩容时,rehash,可能会形成链表环,导致查找的死循环)
添加新元素为链表头结点(1.8为尾结点)
。当链表的长度超过8(根据泊松分布,8为极小概率事件)
且数组的长度超过64(当数组小于64的时候,数组+链表的方式查询效率更高)
的时候,将链表转成红黑树(红黑树是一种近似平衡二叉树,相比其他平衡二叉树,维护平衡的代价相对较低,二叉搜索树在极端情况下会退化成链表)
,提升查找效率,由O(n)→O(logn);否则就进行扩容操作。
扩容操作
当数组大小超过阈值并且发生hash冲突的时候,会进行扩容操作,扩容为之前的2倍大小。扩容时,当红黑树结点数量小于6的时候从红黑树转成链表。
取值操作
获取数据时,计算key的hash值,然后根据这个hash值再hash并结合数组长度,定位到下标,并通过equals方法对比key查找数据。
删除操作
删除数据时,hash查找,如果是单元素直接置null,链表断开链接,红黑树删除元素再平衡。
缩容操作
没有动态缩容