HashMap扩容原理(带源码分析)

 HashMap的扩容原理

1.扩容流程图

注:拆分链表的规则

这里拆分链表时的一个比较:e.hash & oldCap == 0 意思是:某一个节点的hash值和老数组容量求&运算。如果等于0,当前元素在老数组中的位置就是在新数组中的位置。如果不等于0,它存储的位置是:原来老数组中的位置 + 老数组容量。

例:假设老数组容量是16,新数组就是32

现在要拆分标明的这个节点,该点在老数组中的位置是3。如果该点的hash & oldCap == 0。则把该点挂在新数组的也是3的位置。如果不为0,则挂在 3 + 16 = 19 的位置。

2.扩容源码分析(有注释) jdk8
//扩容、初始化数组
final Node<K,V>[] resize() {Node<K,V>[] oldTab = table;//如果当前数组为null的时候,把oldCap老数组容量设置为0int oldCap = (oldTab == null) ? 0 : oldTab.length;//老的扩容阈值int oldThr = threshold;int newCap, newThr = 0;//判断数组容量是否大于0,大于0说明数组已经初始化if (oldCap > 0) {//判断当前数组长度是否大于最大数组长度if (oldCap >= MAXIMUM_CAPACITY) {//如果是,将扩容阈值直接设置为int类型的最大数值并直接返回threshold = Integer.MAX_VALUE;return oldTab;}//如果在最大长度范围内,则需要扩容  OldCap << 1等价于oldCap*2//所以每次扩容就是原来的两倍//运算过后判断是不是最大值并且oldCap需要大于16else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&oldCap >= DEFAULT_INITIAL_CAPACITY)newThr = oldThr << 1; // double threshold  等价于oldThr*2}//如果oldCap<0,但是已经初始化了,像把元素删除完之后的情况,那么它的临界值肯定还存在,       			如果是首次初始化,它的临界值则为0else if (oldThr > 0) // initial capacity was placed in thresholdnewCap = oldThr;//数组未初始化的情况,将阈值和扩容因子都设置为默认值else {               // zero initial threshold signifies using defaultsnewCap = DEFAULT_INITIAL_CAPACITY;// 默认容量16// 默认加载因子 * 默认容量 = 16 * 0.75 = 12// 阈值,超过就触发扩容逻辑newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);}//初始化容量小于16的时候,扩容阈值是没有赋值的if (newThr == 0) {//创建阈值float ft = (float)newCap * loadFactor;//判断新容量和新阈值是否大于最大容量newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?(int)ft : Integer.MAX_VALUE);}//计算出来的阈值赋值threshold = newThr;@SuppressWarnings({"rawtypes","unchecked"})//根据上边计算得出的容量 创建新的数组       Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];//赋值table = newTab;// table就是我们存储数据的数组!//扩容操作,判断不为空证明不是初始化数组if (oldTab != null) {//遍历数组for (int j = 0; j < oldCap; ++j) {Node<K,V> e;//判断当前下标为j的数组如果不为空的话赋值个e,进行下一步操作if ((e = oldTab[j]) != null) {//将数组位置置空oldTab[j] = null;//判断是否有下个节点if (e.next == null)//如果没有,就重新计算在新数组中的下标并放进去newTab[e.hash & (newCap - 1)] = e;//有下个节点的情况,并且判断是否已经树化else if (e instanceof TreeNode)//进行红黑树的操作((TreeNode<K,V>)e).split(this, newTab, j, oldCap);//有下个节点的情况,并且没有树化(链表形式)else {//比如老数组容量是16,那下标就为0-15//扩容操作*2,容量就变为32,下标为0-31//低位:0-15,高位16-31//定义了四个变量//        低位头          低位尾Node<K,V> loHead = null, loTail = null;//        高位头		   高位尾Node<K,V> hiHead = null, hiTail = null;//下个节点Node<K,V> next;//循环遍历do {//取出next节点next = e.next;//通过 与操作 计算得出结果为0if ((e.hash & oldCap) == 0) {//如果低位尾为null,证明当前数组位置为空,没有任何数据if (loTail == null)//将e值放入低位头loHead = e;//低位尾不为null,证明已经有数据了else//将数据放入next节点loTail.next = e;//记录低位尾数据loTail = e;}//通过 与操作 计算得出结果不为0else {//如果高位尾为null,证明当前数组位置为空,没有任何数据if (hiTail == null)//将e值放入高位头hiHead = e;//高位尾不为null,证明已经有数据了else//将数据放入next节点hiTail.next = e;//记录高位尾数据hiTail = e;}} //如果e不为空,证明没有到链表尾部,继续执行循环while ((e = next) != null);//低位尾如果记录的有数据,是链表if (loTail != null) {//将下一个元素置空loTail.next = null;//将低位头放入新数组的原下标位置newTab[j] = loHead;}//高位尾如果记录的有数据,是链表if (hiTail != null) {//将下一个元素置空hiTail.next = null;//将高位头放入新数组的(原下标+原数组容量)位置newTab[j + oldCap] = hiHead;}}}}}//返回新的数组对象return newTab;}
小结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/817024.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CORS 跨域问题解决预检(OPTIONS)请求解释

场景&#xff1a; 业务要求从把系统B嵌入到系统A中&#xff0c;系统A和系统B是完成不同的两个域名&#xff0c;前端同事完成系统嵌入后&#xff0c;从A系统内部调用B系统的接口时候发现跨域错误&#xff08;CORS error&#xff09;&#xff0c;如下&#xff1a; 什么是跨域&…

vscode开发 vue3+ts 的 uni-app 微信小程序项目

创建uni-app项目&#xff1a; # 创建用ts开发的uni-app npx degit dcloudio/uni-preset-vue#vite-ts 项目名称 # 创建用js开发的uni-app npx degit dcloudio/uni-preset-vue#vite 项目名称VS Code 配置 为什么选择 VS Code &#xff1f; HbuilderX 对 TS 类型支持暂不完善VS…

(学习日记)2024.04.16:UCOSIII第四十四节:内存管理

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

手机数据恢复工具

下载地址&#xff1a;手机数据恢复工具.zip Android/HarmonyOS 文件误删是日常使用电子设备时经常遇到的问题&#xff0c;也许一不小心就就可能会误删。 俗话说&#xff1a;数据无价&#xff0c;一但想要找回一些被删除的文件&#xff0c;就需要耗费大量的精力和财力来恢复文…

【宝德PI300T G2智能小站开发教程(三)】centos配置系统开发源

目录 一.前言 二.配置dns服务器 三.测试连通性 四.设置更新源文件 一.前言 openeular系统的宝德板子没有更新的国内源,要如何配置? 二.配置dns服务器 vi /etc/resolv.conf 添加如下内容: nameserver 8.8.8.8 nameserver 114.114.114.114 三.测试连通性 ping www.ba…

vscode远程连接centos

文章目录 vacode连接linux1. 安装插件2. 查看配置3. 打开ssh4. 远程连接 vacode连接linux 1. 安装插件 在扩展栏搜索remote &#xff0c;找到Remote Development插件&#xff0c;进行安装&#xff1a; 2. 查看配置 打开自己的linux终端&#xff0c;输入ifconfig&#xff0c;…

Laravel/Lumen 中使用 Echo + Socket.IO-Client 实现网页即时通讯广播

此处以 Lumen 9 框架为例说明如何调试通过 Echo 服务端以及客户端 如果你是 Laravel/Lumen 10.47 用户&#xff0c;可以先了解官方的 Laravel Reverb。注意 Laravel Reverb 仅支持 Laravel/Lumen 10.47 以及 PHP 8.2Laravel Reverb 参考官网&#xff1a;https://laravel.com/d…

CSS导读 (复合选择器 下)

&#xff08;大家好&#xff0c;今天我们将继续来学习CSS的相关知识&#xff0c;大家可以在评论区进行互动答疑哦~加油&#xff01;&#x1f495;&#xff09; 目录 2.5 伪类选择器 2.6 链接伪类选择器 2.6.1 链接伪类注意事项 2.6.2 链接伪类选择器实际开发中的写法 2.7 …

智慧医疗app

智慧医疗app是一套融合物联网、云计算和大数据等技术&#xff0c;以患者数据为中心的医疗服务模式&#xff0c;致力于为患者提供更加便捷、高效的医疗服务。 在线挂号、在线问诊、电子病历记录、健康管理以及药品购买等。患者可以通过app选择医生和挂号时间&#xff0c;并在线…

ROS2从入门到精通1-3:详解ROS2动作通信机制与自定义动作

目录 0 专栏介绍1 动作通信模型2 动作模型实现(C)3 动作模型实现(Python)4 自定义动作 0 专栏介绍 本专栏旨在通过对ROS2的系统学习&#xff0c;掌握ROS2底层基本分布式原理&#xff0c;并具有机器人建模和应用ROS2进行实际项目的开发和调试的工程能力。 &#x1f680;详情&a…

蓝桥杯嵌入式2021年第十二届第一场省赛主观题解析

1 题目 2 代码 /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "tim.h" #include "usart.h" #include "gpio.h"/* Private includes…

武汉星起航助力跨境电商,专业选品与全方位服务引领行业新风尚

在全球跨境电商浪潮的推动下&#xff0c;越来越多的卖家纷纷将目光投向了这片广阔的市场。然而&#xff0c;如何在这片蓝海中脱颖而出&#xff0c;成为众多卖家关注的焦点。武汉星起航电子商务有限公司以其专业的选品建议和全方位的服务&#xff0c;为卖家们提供了一条成功的捷…

新零售行业门店管理方案详解,人人都可以是好店长

在之前的文章中&#xff0c;我们分别介绍了新零售业的全面解决方案&#xff0c;包括门店管理解决方案、商品经营方案、会员管理解决方案&#xff0c;以及这些方案所包含的分析指标&#xff0c;吸引了不少对新零售转型感兴趣的企业主。 后续我们会将这些内容拆解开来&#xff0…

LeetCode-热题100:104. 二叉树的最大深度

题目描述 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a; root [3,9,20,null,null,15,7] 输出&#xff1a; 3 示例 2&#xff1a; 输入&#xff1a; root …

【数字IC/FPGA】什么是无符号数?什么是有符号数?

进制 虽然在日常生活中&#xff0c;我们已经习惯了使用10进制数字&#xff0c;但在由数字电路构成的数字世界中&#xff0c;2进制才是效率更高的选择。 10进制与2进制 10进制&#xff08;decimal&#xff09;计数法&#xff08;一般也叫阿拉伯计数法&#xff09;是在日常生活…

LLM生成模型在生物单细胞single cell的应用:scGPT

参考&#xff1a; https://github.com/bowang-lab/scGPT https://www.youtube.com/watch?vXhwYlgEeQAs 主要是把单细胞测序出来的基因表达量的拼接起来构建成的序列&#xff0c;这里不是用的基因的ATCG&#xff0c;是直接用的基因名称 训练数据&#xff1a;scGPT全人模型是在3…

第⑫讲:Ceph集群OSD扩缩容中Reblanceing数据的重分布

文章目录 1.Reblanceing数据重分布的概念2.验证Reblanceing触发的过程3.Reblanceing细节4.临时关闭Reblanceing机制 1.Reblanceing数据重分布的概念 当集群中OSD进行扩缩容操作后&#xff0c;会触发一个Reblanceing数据重分布的机制&#xff0c;简单的理解就是将扩缩容前后OSD…

【Hello算法】 > 第 1 关 > 初识 算法 与 复杂度分析

初识 算法 与 复杂度分析 What are algorithms and data structures ?-什么是算法与数据结构&#xff1f;How to conduct complexity analysis ?-如何进行复杂性分析&#xff1f;时间复杂度空间复杂度 小结Tips&#xff1a; ————————————————————————…

Day101:漏洞发现-漏扫项目篇NucleiYakitGobyAfrogXrayAwvs联动中转被动

目录 特征类-三方Poc调用&模版Poc调用 案例1&#xff1a;单点对某特征点进行安全评估 Goby-综合类 Nuclei-较综合类 Afrog-特征类 Yakit-可特征可综合 案例2&#xff1a;新型对某特征点进行安全评估 综合类-主动漏扫&中转联动&被动联动 案例1&#xff1a;…

移动开发避坑指南——内存泄漏

在日常编写代码时难免会遇到各种各样的问题和坑&#xff0c;这些问题可能会影响我们的开发效率和代码质量&#xff0c;因此我们需要不断总结和学习&#xff0c;以避免这些问题的出现。接下来我们将围绕移动开发中常见问题做出总结&#xff0c;以提高大家的开发质量。本系列文章…