HashMap底层原理分析

目录

一、大致分析HashMap

二、Hashmap源码分析

1.默认成员变量

2.构造方法

3.底层实现过程

三、总结

一、大致分析HashMap

HashMap的底层结构是哈希桶,哈希桶(链地址法/开散列法)是解决哈希表冲突的一种方法。哈希桶可以理解为盛放不同key链表的容器,在这里我们可以把每个key的位置看作是一个桶,桶里放了一个链表,故该方法也叫分离链接法。在HashMap中,采用数组+链表的方式来实现对数据的储存。当满足一定条件时,链表会转换为红黑树,保证插入/删除/查找时间复杂度为O(1)。

哈希桶示意图:

二、Hashmap源码分析

1.默认成员变量

哈希桶的默认大小(数组大小)为1<<4=16

默认的负载因子为0.75

当链表长度大于8且哈希桶的大小大于64时,链表会转化为红黑树

当红黑树的节点小于6时,红黑树会转化为链表

哈希桶的最大容量1<<30

2.构造方法

两个参数的构造方法,第一个为哈希桶容量,第二个为负载因子。哈希桶容量大于0且小于等于最大容量,负载因子大于0。针对于this.threshold=tableSizeFor(initialCapacity),表明哈希桶的容量发生了改变,具体怎么改变下面解释。

一个参数的构造方法,参数为哈希桶容量,负载因子默认为0.75。

无参数的构造方法,负载因子默认为0.75,默认没有分配哈希桶容量。问题来了,那么哈希桶容量是多少?下面解释

3.底层实现过程

看它的put方法:

拿到key之后调用了hash方法:

key传给hash后判断key,key为空返回0,key不为空,返回key.hashCode()^(h>>>16),我们发现在计算hash时hashCode结束后还异或了h>>>16,这样做是为了得到更均匀的数字。计算完hash后调用了putVal方法:

先看前面一点,将hash传给putVal方法,先创建了tab数组,没有内存。进入第一个if语句,n=(tab=resize()).length,n为数组的容量,调用了resize方法:

table没有内存→oldTab也没有内存→oldCap=0→oldThr=0(threshold没有赋值默认为0)→进入最后一个else语句,newCap=1<<<4=16→创建newTab数组,容量为16→赋值于table

即没有参数时,在第一次put时哈希桶容量默认为16。

hash有了,数组有了,该寻找下标,我们认为的下标=hash%table.length(),底层是这样的吗?

发现下标i=(tab.length-1)&hash,其实当哈希桶容量为2的次幂时,(tab.length-1)&hash=hash%table.length() ,也就是HashMap会保证哈希桶的容量为2的次幂。问题来了,当我们自己规定哈希桶容量时,怎么保证容量为的次幂。回想我们知道指定哈希桶容量时是否还有this.threshold=tableSizeFor(initialCapacity),这么一句话就是在改变哈希桶的容量为2的次幂。

具体看tableSizeFor这个方法:

这个方法时让容量去靠近最近的2次幂,例如规定容量为11,则转换后容量实际为16(转化后的容量要大于等于规定的容量)。

确定位置之后放元素:

数组下标元素为空,直接放进去;如果不为空,先判断是否是红黑树,是红黑树按照树的方式插入,不是的话按照链表尾插法插入。插入完成之后判断个数是否大于7,大于7考虑红黑树。

treeifyBin(tab,hash)方法:

当哈希桶容量大于64转变为红黑树,不大于64调用resize()方法扩容,容量变为之前的两倍。

三、总结

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
HashMap的底层实现原理1.8版本主要涉及到哈希算法、数组和链表/红黑树的数据结构以及扩容机制。首先,hashcode()方法会根据对象的特定规则生成一个哈希码,用于确定对象在数组中的存储位置。如果两个对象的equals()方法返回true,则它们的哈希码必须相等。 HashMap内部使用一个Entry数组来存储键值对,数组的每个位置称为。每个Entry对象包含键值对的信息,以及一个指向下一个Entry的指针。当向HashMap中添加键值对时,根据键的哈希码找到对应的,如果该为空,则直接将键值对存入该;如果不为空,则遍历链表(或者当链表长度达到一定阈值时,将链表转换为红黑树),找到合适的位置插入新的键值对。 在1.8版本中,当链表长度超过8,则将链表转换为红黑树,这是为了提高查询效率。红黑树的查询时间复杂度为O(logN),相比链表的O(N)更低。当红黑树节点数量小于6时,又会将红黑树转换回链表,以节省内存。 HashMap还有一个重要的机制是扩容。当哈希表的大小超过了负载因子与的数量的乘积时,就会自动触发扩容操作。扩容会创建一个更大的数组,并将所有的键值对重新分配到新数组的中,这个过程是比较耗时的。扩容的目的是为了减少哈希冲突,提高查询性能。 总的来说,HashMap的底层实现原理1.8版本主要依靠哈希算法、数组和链表/红黑树的数据结构以及扩容机制来实现高效的键值对存储和检索。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [1.8版本HashMap底层原理分析](https://blog.csdn.net/m0_61750910/article/details/123204007)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ambition…

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值