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…...

对话机器人技术解说
一、RAG介绍 如何不通过微调模型来提高LLM性能,检索增强生成(RAG)是未来的发展方向。 Embedding:将文档的句子或单词块转换为数字向量。就向量之间的距离而言,彼此相似的句子应该很近,而不同的句子应该离…...

红黑树底层封装map、set C++
目录 一、框架思考 三个问题 问题1的解决 问题2的解决: 问题3的解决: 二、泛型编程 1、仿函数的泛型编程 2、迭代器的泛型编程 3、typename: 4、/--重载 三、原码 红黑树 map set 一、框架思考 map和set都是使用红黑树底层&…...

压力给到 Google,OpenAI 发布 GPT-4o 来了
北京时间5月14日凌晨1点,OpenAI 开启了今年的第一次直播,根据官方消息,这次旨在演示 ChatGPT 和 GPT-4 的升级内容。在早些时候 Sam Altman 在 X 上已经明确,「我们一直在努力开发一些我们认为人们会喜欢的新东西,对我…...

【SpringSecurity源码】过滤器链加载流程
theme: smartblue highlight: a11y-dark 一、前言及准备 1.1 SpringSecurity过滤器链简单介绍 在Spring Security中,过滤器链(Filter Chain)是由多个过滤器(Filter)组成的,这些过滤器按照一定的顺序对进…...

第9章.Keil5-MDK软件简介
目录 0. 《STM32单片机自学教程》专栏 9.1 主界面 9.2 文本格式编辑 9.3 代码提示&语法检测&代码模版 9.4 其他小技巧 9.4.1 TAB 键的妙用 9.4.2 快速定位函数/变量被定义的地方 9.4.3 快速注释与快速消注释 9.4.4 快速打开头文件 9.4.5 查找替换…...

mysql中utf8字符集中文字节长度统计如何统计到2个字节一个汉字
在 MySQL 的 utf8 字符集中(也被称为 utf8mb3),中文字符实际上并不是用2个字节来表示的,而是使用3个字节。这是 UTF-8 编码的一个特性,它使用1到4个字节来表示一个字符,具体取决于字符的 Unicode 码点。 对…...

如何实现Linux双网卡同时连接内网和外网的配置?
博主猫头虎的技术世界 🌟 欢迎来到猫头虎的博客 — 探索技术的无限可能! 专栏链接: 🔗 精选专栏: 《面试题大全》 — 面试准备的宝典!《IDEA开发秘籍》 — 提升你的IDEA技能!《100天精通鸿蒙》 …...

ASCLL码表以及字符的相加减
ASCLL码表完整版及解释_acssll码-CSDN博客 #include <getopt.h> #include <stdio.h> #include <stdlib.h>#define MAX_PATH 256 char filename[MAX_PATH 5];int isdigit(int c) {if (c > 0 && c < 9)return 1;return 0; }int main(int argc…...

一键修复所有dll缺失,教大家解决丢失的dll文件
修复所有DLL(动态链接库)文件缺失的问题通常不可能通过单一的"一键修复"按钮来实现,因为DLL文件缺失可能由各种不同的原因导致,比如应用程序安装不正确、病毒感染、或系统文件损坏等。 使用内置的系统文件检查器&#x…...

wsl2安装rancher并导入和创建k8s集群
环境准备 安装wsl2点击此文]ubuntu20.04安装docker 点击此文,安装完成后docker镜像仓库改成阿里云镜像加速地址.如果不熟请点击此文 docker 安装rancher 启动wsl,根据官方文档以root身份执行 sudo docker run -d --restartunless-stopped -p 80:80 -p 443:443 --privileged …...