HashMap的底层原理

目录

1、数据结构

2.哈希函数

3. 插入操作

4. 查找操作

5. 扩容操作


1、数据结构

从java8开始,为了优化性能,HashMap采用了数组+链表+红黑树的结构

  • 数组:我们称之为哈希桶,是HashMap中的基础数据结构,每个数组中的元素称为一个桶,用于存放链表和红黑树的头结点。数组的索引是由键的哈希值经过一定处理得到的
  • 链表:当多个键值的哈希映射到同一个桶中,链表中的每个节点包含一个键值对以及下一个节点的引用
  • 红黑树:当链表的长度达一定程度(默认为8),并且数组的长度达到64时,链表会转换成红黑树,红黑树是一种自平衡的二叉树,将查询、插入和删除的时间复杂度从链表的O(n)降低到O(logN)、从而提升性能

2.哈希函数

HashMap使用哈希函数将建的哈希码(通过hash函数返回的值)转换为数组的索引。

常见的哈希函数有:

  1. 直接定制法--(常用) 取关键字的某个线性函数为散列地址:Hash(Key)= A*Key + B 优点:简单、均匀 缺点:需要事先知道关 键字的分布情况 使用场景:适合查找比较小且连续的情况
  2. 除留余数法--(常用) 字符串中第一个只出现一次字符 设散列表中允许的地址数为m,取一个不大于m,但最接近或者等于m的质数p作为除数,按照哈希函数: Hash(key) = key% p(p<=m),将关键码转换成哈希地址
  3. 平方取中法--(了解) 假设关键字为1234,对它平方就是1522756,抽取中间的3位227作为哈希地址; 再比如关键字为4321,对 它平方就是18671041,抽取中间的3位671(或710)作为哈希地址 平方取中法比较适合:不知道关键字的分 布,而位数又不是很大的情况 比特就业课
  4.  折叠法--(了解) 折叠法是将关键字从左到右分割成位数相等的几部分(最后一部分位数可以短些),然后将这几部分叠加求和, 并按散列表表长,取后几位作为散列地址。 折叠法适合事先不需要知道关键字的分布,适合关键字位数比较多的情况
  5. 随机数法--(了解) 选择一个随机函数,取关键字的随机函数值为它的哈希地址,即H(key) = random(key),其中random为随机数 函数。 通常应用于关键字长度不等时采用此法

然后,对哈希码进行扰动处理,通过 (h = key.hashCode()) ^ (h >>> 16) 操作,将哈希码的高 16 位与低 16 位进行异或运算,以减少哈希冲突的概率。

最后,使用扰动后的哈希值与数组长度减 1 进行按位与运算 (n - 1) & hash,得到数组的索引。这里要求数组长度必须是 2 的幂次方,这样 (n - 1) & hash 就相当于 hash % n,但按位与运算的效率更高。

3. 插入操作

当调用put(key,value)方法出入键值对时,HashMap的插入过程如下:

1.计算键的哈希值,通过哈希函数得到数组的索引。

2.如果该索引对应的桶为空,则直接创建一个新的节点并放入该桶中。

3.如果该索引对应的桶不为空,则需要处理哈希冲突: 

  • 如果桶中的节点是红黑树节点,则调用红黑树的插入方法将键值对插入到红黑树中
  • 如果桶中的节点是链表节点,则遍历链表,查找是否存在相同的键。
  • 如果存在,则更新该键对应的值;如果不存在,则在链表尾部插入新节点。插入后,如果链表的长度达到 8 且数组长度达到 64,则将链表转换为红黑树。

 4.插入完成后,检查 HashMap 的元素数量是否超过阈值(容量 * 负载因子),如果超过则进行   扩容操作。

4. 查找操作

当调用get(key)方法查找建对应的值时,HashMap的查找过程如下:

  1. 计算键的哈希值,通过哈希函数得到数组的索引。
  2. 如果该索引对应的桶为空,则返回 null
  3. 如果该索引对应的桶不为空,则需要进一步查找:
  • 如果桶中的节点是红黑树节点,则调用红黑树的查找方法查找该键对应的值。
  • 如果桶中的节点是链表节点,则遍历链表,查找是否存在相同的键。如果存在,则返回该键对应的值;如果不存在,则返回 null

5. 扩容操作

HashMap 的扩容操作主要是为了减少哈希冲突,提高性能。当 HashMap 的元素数量超过阈值(容量 * 负载因子)时,会触发扩容操作。扩容过程如下:

  1. 创建一个新的数组,其长度为原数组长度的 2 倍。
  2. 遍历原数组中的每个桶,将桶中的节点重新计算哈希值并插入到新数组中。对于链表节点,会根据新的哈希值将链表拆分为两个链表,分别插入到新数组的不同位置;对于红黑树节点,会进行拆分和重新插入操作,如果拆分后红黑树的节点数量小于等于 6,则将红黑树转换为链表。
  3. 将新数组作为 HashMap 的底层数组。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值