HashMap中的put()方法

news2025/2/24 18:17:38

一. HashMap底层结构

HashMap底层是由哈希表(数组),链表,红黑树构成,哈希表存储的类型是一个节点类型,哈希表默认长度为16,它不会每个位置都用,当哈希表中的元素个数大于等于负载因子(0.75)*哈希表长度就会扩容到原来的2倍

二. 底层的一些常量

三. HashMap的put()方法

当插入一个元素时,先利用hash(key)计算该元素的hash值 

 

这是计算哈希值的具体实现,如果该对象为空哈希值为0,否则调用这个对象重写的hashCode方法在和其向右无符号右移16位做异或运算,这样做的目的是减少hash冲突 

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {

        //tab是底层的哈希表,p是要遍历链表或红黑树的一个引用,n是哈希表长度
        Node<K,V>[] tab; Node<K,V> p; int n, i;

          
        //如果哈希表为空或哈希表的长度位0,则调用resize()方法初始化哈希表,并将长度赋给n
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;

        //用(n-1)&hash来定位该元素要存放在哈希表中的哪个位置
        //如果该位置为空,则表示之前没有存放过元素,不存在元素重复的情况,直接放入该位置即可
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);

        //否则,该位置不为空,表示之前存放有元素
        else {
            //e是用来标记重复元素的
            Node<K,V> e; K k;

            //这里是判断是否是重复元素,只判断第一个位置是否是重复元素
            //p表示哈希表中的元素
            //如果两者的hash值相同且两个元素的地址相同,那么肯定是重复元素
            //如果两者的hash值相同,地址不同,但equals()比较的内容相同,则是重复元素
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))

                //记录重复元素
                e = p;

             //否则如果第一个元素不是重复元素,且p的类型是红黑树结构,则调用红黑树的put方法进行插入
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);

            //否则第一个元素不是重复元素且hash表中是链表结构
            //一次遍历链表后面的元素,看是否还有重复元素,有就标记,到尾部没有就插入
            else {
                for (int binCount = 0; ; ++binCount) {
                      //判断p的下一个是不是空,并将p的下一个赋值给e
                    if ((e = p.next) == null) {
                          
                         //找到链表尾部进行插入
                        p.next = newNode(hash, key, value, null);
                          
                         //binCount用来记录链表中的元素个数,插入后判断链表个数
                         //如果大于等于7(这里从0开始,其实实际个数超过8),则链表转为红黑树
                        if (binCount >= TREEIFY_THRESHOLD - 1)
                            treeifyBin(tab, hash);
                        break;
                    }


                    //如果当前要比较的元素(e)不是尾部元素,则判断是否是重复元素
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;//e是重复元素就跳出循环

                    p = e;//不是重复元素就将e赋值给p,相当于继续往下走去判断后面的元素
                }
            }

             //e不为空代表有重复元素
            if (e != null) { // existing mapping for key
                V oldValue = e.value;//用重复元素后面出现的值替换原本的值

                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;

                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();//如果哈希表中的元素大于负载因子(0.75)*哈希表长度,则哈希表进行扩容
        afterNodeInsertion(evict);
        return null;
    }

 

当哈希表中某个位置的链表个数大于8,则调用treeifyBin但此时不一定树化,还有一个条件,当哈希表的长度大于MIN_TREEIFY_CAPACITY(64)时才树化,否则只是调用resize()进行扩容

四. 底层哈希表的扩容

1.当向哈希表为null或哈希表的长度为0,即哈希表还没有初始化时会扩容为默认长度16

2.当哈希表中的位置被用了负载因子(0.75)*哈希表的长度时会扩容为原来的2倍

3.当哈希表中某个链表的个数达到8,但哈希表的长度未到64会扩容为原来的2倍

 

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

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

相关文章

简单的手动实现spring中的自动装配案例

简简单单的实现一个spring中的自动装配和容器管理的小骚操作。 1&#xff0c;创建AutoSetBean.java 使用injectBeans静态方法&#xff0c;可以扫描指定包下的所有带MyInject注解的字段&#xff0c;如果在beans的Map中存在这个字段的实例化类&#xff0c;则执行装配。 import…

c语言题目:成绩管理系统

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

Windows系统下载安装ngnix

一 nginx下载安装 nginx是HTTP服务器和反向代理服务器&#xff0c;功能非常丰富&#xff0c;在nginx官网首页&#xff0c;点击download 在download页面下&#xff0c;可以选择Stable version稳定版本&#xff0c;点击下载 将下载完成的zip解压即可&#xff0c;然乎在nginx所在…

【MySQL】事务四大特性以及实现原理

事务四大特性 原子性&#xff08;Atomicity&#xff09; 事务中的所有操作要么全部完成&#xff0c;要么全部不执行。如果事务中的任何一步失败&#xff0c;整个事务都会被回滚&#xff0c;以保持数据的完整性。 一致性&#xff08;Consistency&#xff09; 事务应确保数据库…

集智书童 | 英伟达和斯坦福基于 Transformer 的异常检测最新研究!

本文来源公众号“集智书童”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;英伟达和斯坦福基于 Transformer 的异常检测最新研究&#xff01; 在作者推动各种视觉任务性能边界的同时&#xff0c;模型的大小也在相应增长。为了跟上…

SPIN-Diffusion:自我博弈微调提升文本到图像扩散模型性能

扩散模型作为生成AI的关键实体&#xff0c;已经在多个领域展现出了卓越的能力。然而&#xff0c;现有的扩散模型&#xff0c;如Stable Diffusion和SDXL&#xff0c;通常在预训练阶段后需要进行微调以更好地符合人类偏好。最近&#xff0c;研究者们开始尝试使用强化学习&#xf…

昇思MindSpore学习笔记4-03生成式--Diffusion扩散模型

摘要&#xff1a; 记录昇思MindSpore AI框架使用DDPM模型给图像数据正向逐步添加噪声&#xff0c;反向逐步去除噪声的工作原理和实际使用方法、步骤。 一、概念 1. 扩散模型Diffusion Models DDPM(denoising diffusion probabilistic model) &#xff08;无&#xff09;条件…

06-6.4.4 拓扑排序

&#x1f44b; Hi, I’m Beast Cheng &#x1f440; I’m interested in photography, hiking, landscape… &#x1f331; I’m currently learning python, javascript, kotlin… &#x1f4eb; How to reach me --> 458290771qq.com 喜欢《数据结构》部分笔记的小伙伴可以…

计算机网络浅谈—什么是 OSI 模型?

开放系统通信&#xff08;OSI&#xff09;模型是一个代表网络通信工作方式的概念模型。 思维导图 什么是 OSI 模型&#xff1f; 开放系统互连 (OSI) 模型是由国际标准化组织创建的概念模型&#xff0c;支持各种通信系统使用标准协议进行通信。简单而言&#xff0c;OSI 为保证…

C++左值右值

在C中&#xff0c;左值&#xff08;lvalue&#xff09;和右值&#xff08;rvalue&#xff09;是表达式分类的关键概念&#xff0c;它们主要影响表达式的赋值、函数调用以及操作符的使用方式。这些概念在C11及以后的版本中变得更加重要&#xff0c;因为引入了移动语义和右值引用…

蓄势高飞逐“新”空,卓翼飞思助力打造低空经济产业领域人才智库

2024年&#xff0c;“低空经济”首次写入政府工作报告&#xff0c;掀开新兴产业的崭新一页&#xff0c;而后迅速在全国各地呈现如火如荼的发展态势。这片蕴藏着巨大潜力和产业的蓝海&#xff0c;正蓄势聚能、乘势而起&#xff0c;站在发展的新风口上&#xff0c;面对新前景和新…

MongoDB集群搭建-最简单

目录 前言 一、分片概念 二、搭建集群的步骤 总结 前言 MongoDB分片&#xff08;Sharding&#xff09;是一种水平扩展数据库的方法&#xff0c;它允许将数据分散存储在多个服务器上&#xff0c;从而提高数据库的存储容量和处理能力。分片是MongoDB为了应对大数据量和高吞吐量需…

ONLYOFFICE最新8.1版本——桌面编辑器简单测评

前言 大家好&#xff0c;我是小雨&#xff0c;看到最近ONLYOFFICE更新了最新的版本&#xff0c;更新了一下当前版本来具体的测评一下&#xff0c;先来看看官网提供的各类更新信息&#xff0c;下面是我找到的三个主页&#xff0c;包括功能演示链接&#xff0c;官网连接以及专门…

Ros2中goal_handle状态SUCCEED及ACCEPTED及CANCLED在rclpy中的死循环(彻底解决版本)

承接上文&#xff0c;遇到了在动作通信开发中&#xff0c;使用rclpy编写代码进行feedback等操作&#xff0c;但所有逻辑均编写完后&#xff0c;却无法将goal_handle提交为succeed状态&#xff0c;之前的解决方案是更改自己重写的execute()函数名为my_execute()并且在提交SUCCEE…

开始尝试从0写一个项目--后端(二)

实现学生管理 新增学生 接口设计 请求路径&#xff1a;/admin/student 请求方法&#xff1a;POST 请求参数&#xff1a;请求头&#xff1a;Headers&#xff1a;"Content-Type": "application/json" 请求体&#xff1a;Body&#xff1a; id 学生id …

N5 使用Gensim库训练Word2Vec模型

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊# 前言 前言 这周学习训练一个Word2Vec模型&#xff0c;并进行一些基本的词向量操作。 Word2Vec 模型 Word2Vec 是一种基于神经网络的词向量表示方法&#x…

零基础STM32单片机编程入门(八)定时器PWM输入实战含源码视频

文章目录 一.概要二.PWM输入框架图三.CubeMX配置一个PWM输入例程1.硬件准备2.创建工程3.调试 四.CubeMX工程源代码下载五.讲解视频链接地址六.小结 一.概要 脉冲宽度调制(PWM)&#xff0c;是英文“Pulse Width Modulation”的缩写&#xff0c;简称脉宽调制&#xff0c;是利用单…

数学建模算法目标规划

在人们的生产实践中&#xff0c;经常会遇到如何利用现有资源来安排生产&#xff0c;以取得最大经济 效益的问题。此类问题构成了运筹学的一个重要分支—数学规划&#xff0c;而线性规划(Linear Programming 简记 LP)则是数学规划的一个重要分支。特别是在计算机能处理成千上万个…

在电子表格中对多列数据去重

一、数据展示 二、代码 Sub 选中区域数据去重()Dim arr()Dim c, d, id Selection.Counti 0For Each c In SelectionIf c.Value <> "" ThenReDim Preserve arr(0 To i)arr(i) c.Valuei i 1End IfNextarr 一维去重(arr)i 0For Each c In Range("O2&…

35.哀家要长脑子了!--二分

模板 int check() {...} // 检查这个数是否符合相应的要求// 把区间[l, r] 划分成[l, mid] 和 [mid1, r] 时使用 // 找到数组中第一个大于等于某一值得元素或满足特定条件的第一个位置 int bsearch_1(int l, int r){int mid l r >> 1;while(l < r) {if(check(mi…