当添加一个键值对元素时,HashMap发生了什么?

一、认识HashMap基本概念

        首先先来了解一下什么是HashMap,它是Map接口的一个实现类,继承自AbstractMap,基于键值对来存储数据,HashMap底层采用 数组 + 链表/红黑树 作为存储结构,数组类型为 Node[] ,每个 Node 都保存了某个KV键值对元素的 key(键) 、 value (值)、 hash(哈希值) 、 next (下一个元素)

二、进一步理解HashMap的存储机制

        HashMap底层是一个默认长度为16的数组,在数组中保存Entry对象,而每个Entry对象中封装着HashMap中的每一个键值对对象(存有key,value,hash,next)。每次在存储对象时,根据存储的key计算hash值,通过(长度-1)& hash 的算法得到这个元素在数组中存储的下标位置,如果这个数组上已经存放有元素(即产生哈希冲突),那么在这个位置上将以链表的形式存放,使用next指向新添加的元素,形成链表;当该链表的长度大于8(从JDK1.8开始),并且数组的长度大于64时,就会将该链表转为红黑树来存储,这样也缩减了搜索的时间。这也是为什么说HashMap时 数组 + 链表/红黑树 的原因,不是数组的所有位置上都会有红黑树的存在。

三、HashMap的put过程

了解完HashMap的存储机制,现在来说说往HashMap中添加一对键值对的过程会发生什么:

        · 首先会对组的table是否为空进行判断是否需要初始化;

        · 如果不为空,则使用hash方法计算key的哈希值((n- 1) & hash),通过hash值的计算来判断该元素应当存储的位置;

        · 接下来要查看该数组位置上是否已经存在数据;

        · 如果没有数据,就构造个Node<K,V> 节点,将元素存放在该位置中;

        · 如果存在数据,说明发生哈希冲突,继续判断key是否相等;

        · 如果key值相等,就用新的元素数据替换原数据内容;

        · 如果key值不相等,则继续判断判断当前节点类型是树形节点还是链表结点;

        · 如果是树型节点,创造树型节点插入红黑树中;

        · 如果是链表节点,创建普通Node<K,V>加入链表尾部;

        · 再判断判断链表长度大于阈值(默认为8 )并且数组长度大于64,如果满足这两个条件,则将链表转换为红黑树;如果数组长度小于64,则对数组进行扩容;

        · 最后,插入完成之后,判断数组中当前节点数是否大于实际存储空间大小, 如果大于,则调用resize() 方法,按原数组的长度,扩容一倍。

以上便是HashMap的存值过程,还值得一说的是,在插入完成后,对数组进行扩容时,不是根据该数组元素是否存满来判断,而是要根据 当前结点值=数组长度×加载因子 来判断是否需要扩容;加载因子就是用来平衡哈希冲突概率以及空间利用率的存在,默认值为0.75,也就是说当数组容量为16时,如果它元素个数为 16×0.75=12 时便说明,该数组应该扩容了。

  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值