HashMap的存储原理

当HashMap存储元素时,其底层原理涉及以下几个关键步骤:

1. 计算哈希值

  如下图所示,首先进入put方法,put方法返回值调用putVal方法,putVal方法中第一个参数又调用了hash方法,在hash方法中,根据key计算出要添加的这个元素的hash值,是一个int类型的整数,它代表了键对象在哈希表中的位置。

2. 确定存储位置

计算出hash值后,就该进入到putVal方法中了。

在确定存储位置之前,有一些初始扩容操作,如下图所示。

让我们再进入到resize方法中。

这是要用到的几个常量的值。 

如上图所示,第一次添加元素时,HashMap使用数组存储元素 ,初始化容量为16,初始threshold(阈值)为12

然后就是确定存储位置了,让我们再返回到putVal方法中,如下图所示。 HashMap使用hash值和HashMap内部的数组长度来确定元素的存储位置。

3. 处理冲突

(1)当不同的键具有相同的hash值,即发生hash冲突时,HashMap使用链表或者更高效的红黑树来处理冲突。如下图所示。

(2)在链表上,冲突的键值对会被添加到同一位置的链表中。在红黑树上,冲突的键值对会被添加到同一位置的树结构中。

(3)从下图也可以看到,一旦确定了存储位置,HashMap会将键值对存储在对应的数据结构(链表或红黑树)中。如果键对象已经存在于HashMap中,则新的值会覆盖旧的值。

将元素存在链表中: 

将元素存在红黑树中的treeifBin方法。

5. 扩容(Resize)

 HasnMap会在三种情况下进行扩容:

(1) 当创建一个新的 HashMap 实例时,会初始化一个初始容量为16的数组用于存储键值对(上述确定存储位置章节已介绍过)。

(2)如果HashMap的实际存储元素数量达到了负载因子乘以当前数组长度的阈值(默认负载因子为0.75),HashMap会进行扩容操作。如下图所示。

(3)若数组的长度>8且<64时,HashMap会进行扩容操作(在treeifyBin方法中),如下图所示。 

在(2)和(3)中, HashMap会进行扩容操作如下图所示,数组长度扩容到原来的两倍,阈值也增加到原来的两倍。

5.总结:HashMap的数据结构

由前面可知,HashMap是基于哈希表实现的,它的数据结构主要由数组链表红黑树组成。

(1)数组:

①HashMap 的主体是一个数组。

②元素数量是固定的,由HashMap的容量决定。默认情况下,HashMap的初始容量是 16。

2. 链表和红黑树:

①HashMap也使用链表或者红黑树来存储键值对。

②当链表长度超过阈值(默认为 8)时,链表会被转换成红黑树,以提高查找、插入和删除操作的效率。

③这种数据结构的选择(链表还是红黑树)取决于键值对数量的多少和性能的需求。

总结来说,HashMap 的核心数据结构是一个基于数组的哈希表。通过链表或红黑树来解决哈希冲突,HashMap 能够提供高效的插入、查找和删除操作,具有接近常数时间复杂度的性能。

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值