HashMap底层数据结构:
哈希表结构
JDK8之前的哈希表 = 数组+链表
JDK8之后的哈希表 = 数组+链表+红黑树
哈希表是一种增删改查数据,性能相对都较好的数据结构 往HashMap集合中键值对数据时,
底层步骤如下
第1步:当你第一次往HashMap集合中存储键值对时,底层会创建一个长度为16的数组
第2步:把键然后将键和值封装成一个对象,叫做Entry对象
第3步:再根据Entry对象的键计算hashCode值(和值无关)
第4步:利用hashCode值和数组的长度做一个类似求余数的算法,会得到一个索引位置
第5步:判断这个索引的位置是否为null,如果为null,就直接将这个Entry对象存储到这个索引位置 如果不为null,则还需要进行第6步的判断
第6步:继续调用equals方法判断两个对象键是否相同 如果equals返回false,则以链表的形式往下挂 如果equals方法true,则认为键重复,此时新的键值对会替换就的键值对。
HashMap底层需要注意这几点:
1.底层数组默认长度为16,如果数组中有超过12个位置已经存储了元素,则会对数组进行扩容2倍 数组扩容的加载因子是0.75,意思是:16*0.75=12
2.数组的同一个索引位置有多个元素、并且在8个元素以内(包括8),则以链表的形式存储 JDK7版本:链表采用头插法(新元素往链表的头部添加)多线程情况下,可能会造成环形链表 JDK8版本:链表采用尾插法(新元素我那个链表的尾部添加)
3.数组的同一个索引位置有多个元素,当链表长度>=8且数组长度到64,则转成红黑树,扩容时,会进行数据迁移,当红黑树长度<=6时,由红黑树转成链表,Hash碰撞可能造成链表长度过长,影响查询性能。红黑树在一些情况下,查询效率要高于链表
扩容时,如果链表长度超过1,会通过高低算法,把老数组下标对应的链表进行拆分,一半放新数组对应老数组原下标的位置,另一半放新数组下标【老数组下标 + 老数组长度】