23.HashMap的put方法流程
一、put方法的流程图

二、put方法的执行步骤
- 首先,根据key值计算哈希值。
- 然后判断table数组是否为空或者数组长度是否为0,是的话则要扩容,resize()。
- 接着,根据哈希值计算数组下标。
- 如果这个下标位置为空,添加元素即可。
- 如果这个下标位置不为空,则判断此下标位置的首元素的key值与要添加元素的key值是否相同,相同的话,就直接覆盖元素。
- 不相同的话,则判断首元素是否为树节点,是的话,则向这个红黑树中插入元素(在红黑树中插入一个新节点时,首先会遍历树以找到这个新节点应该插入的位置。在这个遍历过程中,也会检查是否已经存在相同key值的节点。如果存在,也会覆盖元素;不存在,则新节点会被插入到正确的位置)。
- 如果是链表的话,那就需要遍历链表,看key是否已经存在,存在则覆盖元素,不存在则在链表尾部插入元素。插入之后,如果链表长度大于等于8,则需要把链表转换为红黑树。
- 最后,待所有元素处理完之后,还要判断容量是否超过阈值,超过了则需要扩容。
三、对应源码:
/*** Computes key.hashCode() and spreads (XORs) higher bits of hash* to lower. Because the table uses power-of-two masking, sets of* hashes that vary only in bits above the current mask will* always collide. (Among known examples are sets of Float keys* holding consecutive whole numbers in small tables.) So we* apply a transform that spreads the impact of higher bits* downward. There is a tradeoff between speed, utility, and* quality of bit-spreading. Because many common sets of hashes* are already reasonably distributed (so don't benefit from* spreading), and because we use trees to handle large sets of* collisions in bins, we just XOR some shifted bits in the* cheapest possible way to reduce systematic lossage, as well as* to incorporate impact of the highest bits that would otherwise* never be used in index calculations because of table bounds.*/static final int hash(Object key) {//1.首先,根据key值计算哈希值。int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}/*** Associates the specified value with the specified key in this map.* If the map previously contained a mapping for the key, the old* value is replaced.** @param key key with which the specified value is to be associated* @param value value to be associated with the specified key* @return the previous value associated with <tt>key</tt>, or* <tt>null</tt> if there was no mapping for <tt>key</tt>.* (A <tt>null</tt> return can also indicate that the map* previously associated <tt>null</tt> with <tt>key</tt>.)*/public V put(K key, V value) {return putVal(hash(key), key, value, false, true);//hash值}/*** Implements Map.put and related methods.** @param hash hash for key* @param key the key* @param value the value to put* @param onlyIfAbsent if true, don't change existing value* @param evict if false, the table is in creation mode.* @return previous value, or null if none*/final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K,V>[] tab; Node<K,V> p; int n, i;//2.然后判断table数组是否为空或者数组长度是否为0,是的话则要扩容,resize()。if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;//3.接着,根据哈希值计算数组下标。
//4.如果这个下标位置为空,添加元素即可。if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null);else {//5.如果这个下标位置不为空,则判断此下标位置的首元素的key值与要添加元素的key值是否相同,相同的话,就直接覆盖元素。Node<K,V> e; K k;if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;//6.不相同的话,则判断首元素是否为树节点,是的话,则向这个红黑树中插入元素else if (p instanceof TreeNode)e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);//7.如果是链表的话,那就需要遍历链表,看key是否已经存在,存在则覆盖元素,不存在则在链表尾部插入元素。不存在则在链表尾部插入元素。插入之后,如果链表长度大于等于8,则需要把链表转换为红黑树。else {for (int binCount = 0; ; ++binCount) {if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);//转为红黑树break;}if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;afterNodeAccess(e);return oldValue;}}++modCount;//8.最后,待所有元素处理完之后,还要判断容量是否超过阈值,超过了则需要扩容。if (++size > threshold)resize();afterNodeInsertion(evict);return null;}
相关文章:
23.HashMap的put方法流程
一、put方法的流程图 二、put方法的执行步骤 首先,根据key值计算哈希值。然后判断table数组是否为空或者数组长度是否为0,是的话则要扩容,resize()。接着,根据哈希值计算数组下标。如果这个下标位置为空&a…...
元类结合__new__
__new__:用来生成骨架 __init__:骨架添加血肉 【一】类中的__new__ class MyClass(object):def __init__(self,name,age):print(f"给当前MyClass类的对象初始化属性的时候会触发__init__")self.name nameself.age age def __call__(self,*args,**kwargs):pri…...
(C语言)队列实现与用队列实现栈
目录 1.队列 1.1队列的概念及结构 1.2 队列的实际应用联想 1.3队列的实现 2. 队列应用——队列实现栈 主要思路 1.队列 1.1队列的概念及结构 队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进…...
字符画生成网站 ascii字符画
_____ / ___/__ ___ / /__/ _ \/ _ \ \___/ .__/ .__//_/ /_/ font推荐:1.Slant 2.Small 3.Small slant https://patorjk.com/software/taag/#pdisplay&fSmall%20Slant&tCpp https://www.kammerl.de/ascii/AsciiSignature.php https://asciia…...
【C -> Cpp】由C迈向Cpp (6):静态、友元和内部类
标题:【C -> Cpp】由C迈向Cpp (6):静态、友元和内部类 水墨不写bug (图片来源于网络) 目录 (一)静态成员 (二)友元 (三)…...
探索Playwright:Python下的Web自动化测试革命
在如今这个互联网技术迅速发展的时代,web应用的质量直接关系着企业的声誉和用户的体验。因此,自动化测试成为了保障软件质量的重要手段之一。今天,我将带大家详细了解一款在测试领域大放异彩的神器——Playwright,并通过Python语言…...
先有JVM还是先有垃圾回收器?很多人弄混淆了
是先有垃圾回收器再有JVM呢,还是先有JVM再有垃圾回收器呢?或者是先有垃圾回收再有JVM呢?历史上还真是垃圾回收更早面世,垃圾回收最早起源于1960年诞生的LISP语言,Java只是支持垃圾回收的其中一种。下面我们就来刨析刨析…...
关于 vs2019 c++20 规范里的一个全局函数 _Test_callable
(1)看名思议,觉得这个函数可以测试其形参是否是可以被调用的函数,或可调用对象? 不,这个名字不科学。有误导,故特别列出。看下其源码(该函数位于 头文件): 辅…...
07-Fortran基础--Fortran指针(Pointer)的使用
07-Fortran基础--Fortran指针Pointer的使用 0 引言1 指针(Poionter)的有关内容1.1 一般类型指针1.2 数组指针1.3 派生类(type)指针1.4 函数指针 2 可运行code 0 引言 Fortran是一种广泛使用的编程语言,特别适合科学计算和数值分析。Fortran 9…...
日期差值,
日期差值 ac代码 #include<iostream> using namespace std; int ans0; int get(int n){int mon[14]{0,31,28,31,30,31,30,31,31,30,31,30,31};ans0;int m_dayn%100;int m_month(n/100)%100;int m_year(n/10000);ansm_day;while(m_month--){//加上月数if((m_year%40&…...
GMV ES6直流变频多联空调机组室外机工作原理
GMV ES6直流变频多联空调机组室外机工作原理如下: 内机为制冷模式运行时,室外机根据室内机的运行负荷需求启动运行,室外换热器作为系统的冷凝器,各制冷室内机的换热器并联作为系统的蒸发器,通过室内机的送回风循环实现…...
中国开源 AI 大模型之光-InternLM2
今天给大家带来 AI 大模型领域的国产之光 - InternLM2,在10B量级开源大模型领域取得了全球 Top 3 的成绩,仅次于 Meta 发布的 Llama-3,在国内则是第一名的存在! 简介 InternLM2是由上海人工智能实验室和商汤科技联合研发的一款大型…...
【嵌入式开发】Arduino人机界面及接口技术:独立按键接口,矩阵按键接口,模拟量按键接口(基础知识介绍)
“生活总是让我们遍体鳞伤,但到后来,那些受伤的地方一定会变成我们最强壮的地方。” 🎯作者主页: 追光者♂🔥 🌸个人简介: 📝[1] CSDN 博客专家📝 🏆[2] 人工智能领域优质创作者🏆 🌟[3] 2022年度博客之星人工智能领域TOP4🌟 🌿[4] …...
element ui Tree树形控件
lazy 是否懒加载子节点,需与 load 方法结合使用 boolean 默认为falseload 加载子树数据的方法,仅当 lazy 属性为true 时生效 function(node, resolve)使用懒加载load不需要再使用data,利用resolve返回值即可注意:第一层的数据要写…...
AI 绘画神器 Fooocus 图生图:图像放大或变化、图像提示、图像重绘或扩充、反推提示词、生成参数提取、所需模型下载
本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里,订阅后可阅读专栏内所有文章。 大家好,我是水滴~~ 本文讲述 Fooocus 的图生图功能,主要内容包括:图像放大或变化、图像提示、图像重绘或扩充、反推…...
yolov8 模型架构轻量化 | 极致降参数量
模型轻量化加速是深度学习领域的重要研究方向,旨在减小模型的体积和计算复杂度,从而提高在资源受限设备上的运行效率,模型参数量在轻量化加速中扮演着至关重要的角色。 首先,模型参数量直接决定了模型的复杂度和存储空间需求。随…...
uniapp 小程序低功耗蓝牙配网 ble配网 物联网
1.获取蓝牙列表 bleList.vue <template><view><button touchstart"startSearch">获取蓝牙列表</button><scroll-view :scroll-top"scrollTop" scroll-y class"content-pop"><viewclass"bluetoothItem&q…...
服务器防火墙有什么用防护策略
随着互联网的飞速发展,服务器的安全问题日益凸显。为了保护服务器免受网络攻击和恶意入侵的威胁,人们引入了防火墙的概念。服务器防火墙作为保护服务器的第一道防线,具有重要的作用。那么服务器防火墙有什么用? 首先,服…...
27.哀家要长脑子了!
目录 1.316. 去除重复字母 - 力扣(LeetCode) 2. 1209. 删除字符串中的所有相邻重复项 II - 力扣(LeetCode 哎哟 烦死了 刚刚不小心退出又没保存 又要写一遍 烦死了 最近刷题不得劲啊 感觉这脑子没长一点 1.316. 去除重复字母 - 力扣&am…...
Redis实战—验证码登录注册
目录 基于Session Controller层 Service层 ServiceImpl层 编辑校验登录状态 ThreadLocal 登录拦截器 添加拦截器到Config Controller层实现 基于Redis ServiceImpl 新增刷新拦截器 添加拦截器到Config 基于Session Controller层 /*** 发送手机验证码*/PostMappi…...
OpenFOAM字典文件关键配置实战指南
1. OpenFOAM字典文件基础认知 第一次接触OpenFOAM的朋友,看到满屏幕的字典文件可能会有点懵。这玩意儿就像乐高积木的说明书,告诉你每个零件该怎么拼。我刚开始用的时候,经常把blockMeshDict和snappyHexMeshDict搞混,结果生成的网…...
从检测到分析:手机位置热力图生成与行为模式挖掘扩展方案
从检测到分析:手机位置热力图生成与行为模式挖掘扩展方案 1. 引言:从“看见”到“看懂” 想象一下,你在一间大型会议室里,墙上挂着十几个监控摄像头。传统的监控系统能告诉你“画面里有手机”,但仅此而已。你无法知道…...
VideoAgentTrek-ScreenFilter视觉盛宴:处理4K超高清屏幕录像的效果与性能挑战
VideoAgentTrek-ScreenFilter视觉盛宴:处理4K超高清屏幕录像的效果与性能挑战 最近在折腾一些屏幕录像的后期处理,特别是那些4K分辨率、高帧率的超高清素材。说实话,直接处理这种级别的视频,对硬件和软件都是不小的考验。我试用了…...
PyCharm中如何快速取消pytest测试模式?5步搞定直接运行Python脚本
PyCharm中如何快速取消pytest测试模式?5步搞定直接运行Python脚本 作为Python开发者,我们经常需要在PyCharm中切换不同的运行模式。有时候,你可能只是想快速运行一个Python脚本,却发现PyCharm固执地以pytest模式执行,…...
智慧小区网络设计避坑指南:华为设备选型、无线覆盖与安全策略实战解析
智慧小区网络设计实战:华为设备选型与无线覆盖避坑指南 当接到智慧小区网络建设项目时,很多工程师会陷入理论完美主义陷阱——画出漂亮的拓扑图,却在实际部署中遭遇信号死角、设备过载、策略冲突等现实问题。本文将从三个真实项目复盘出发&am…...
NaViL-9B参数详解教程:max_new_tokens与temperature协同调优
NaViL-9B参数详解教程:max_new_tokens与temperature协同调优 1. 认识NaViL-9B多模态大模型 NaViL-9B是上海人工智能实验室研发的原生多模态大语言模型,它不仅能处理纯文本问答,还能理解图片内容。这个模型特别适合需要同时处理文字和图像信…...
长期用嘴呼吸,颈肩肌肉代偿性紧张
很多人因为鼻塞、习惯等原因长期用嘴呼吸,却不知道这会导致颈肩肌肉代偿性紧张,影响颈腰椎健康。用嘴呼吸时,头部会不自觉地向前伸、仰起,颈椎长期处于过度前屈或后伸状态,颈部肌肉持续牵拉,容易导致肌肉劳…...
华为交换机MAC地址漂移检测与风暴抑制联动配置指南
1. 华为交换机MAC地址漂移检测原理与实战 刚接触网络运维时,第一次遇到MAC地址漂移报警简直一头雾水。后来才发现,这其实是交换机在提醒我们:"兄弟,你的网络里可能有环路!" MAC地址漂移的本质是同一个MAC地址…...
付费内容访问难题如何破解?开源工具的创新解决方案
付费内容访问难题如何破解?开源工具的创新解决方案 【免费下载链接】bypass-paywalls-chrome-clean 项目地址: https://gitcode.com/GitHub_Trending/by/bypass-paywalls-chrome-clean 在数字内容付费阅读日益普及的今天,如何合法合规地获取所需…...
如何通过开源数据集创造商业价值:Awesome Public Datasets全攻略
如何通过开源数据集创造商业价值:Awesome Public Datasets全攻略 【免费下载链接】awesome-public-datasets A topic-centric list of HQ open datasets. 项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-public-datasets 在数据驱动决策的时代&a…...
