当前位置: 首页 > 后端技术 > Java

HashMap底层原理

时间:2023-04-02 02:07:18 Java

1.存储结构HashMap是Java中数据结构哈希表的实现版本。通过对键值进行哈希函数计算键值对在哈希表中的下标位置,可以快速访问对应的数据,时间复杂度为O(1)。但是由于哈希表数组的长度有限,不同键值的哈希函数计算出的下标位置可能相同,造成哈希冲突。为了解决这个问题,通常会将hash冲突数据组成一个链表挂在hash表bucket节点上面,jdk7及之前的版本都是这样处理的,时间复杂度为O(n),结构如下:jdk8优化了链表结构,在一定条件下将链表转化为红黑树,提高查询效率。红黑树是一棵二叉平衡树,时间复杂度为O(logn)。结构如下:2.访问原理put()方法调用哈希函数hash(key)计算key值hash的哈希值,然后利用哈希值hash和哈希表的长度-1做AND运算得到数组下标;根据数组下标找到目标桶,如果桶中没有元素,则根据键值对新建节点Node,并赋值给桶;如果当前bucket上有一个链表,且头节点匹配(hash值相等,key值相同,或者equals相等),则替换头节点上的值;如果第2、3步不满足,当前桶上的头节点是树结构节点类型TreeNode,则插入操作转为红黑树;如果2、3、4不满足,则遍历链表;1)如果链表中有结点匹配,则进行值置换;2)如果没有节点匹配,则追加到链表尾部;(jdk7采用头插入方式,jdk8采用尾插入方式)3)检查链表长度是否超过TREEIFY_THRESHOLD(默认大小为8),如果超过则执行红黑树转换操作;执行完以上操作后,检查当前键值对比例是否超过负载率,如果超过则扩容。get()方法根据key计算哈希值,进一步计算哈希表的目标下标索引;如果目标桶的头节点匹配,则返回头节点的值;如果目标桶是红黑树,则在红黑树上搜索;如果不是红黑树,则遍历链表;如果没有匹配,返回null;3.扩容一般情况下,当键值对的比例超过负载因子时,就会触发扩容。每次扩容后的容量都是之前容量的两倍。四、线程不安全