HashMap中的putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict)解读

article/2025/8/16 11:13:38

在面试中我们会经常遇到关于HashMap的问题,这里我写了我对HashMap里面一个挺重要的方法 putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict)的理解,下面就是我对这个方法的理解。

其实putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict)方法我们是没有办法直接调用的,其实在我们使用put(K key,V val)时,它里面的内部就调用了putVal方法。

public V put(K key, V value) {return putVal(hash(key), key, value, false, true);}

先讲讲putVal方法里面的几个参数的作用

 /**** @param hash  由key计算出来的 hash值* @param key   要存储的key* @param value  要存储的value* @param onlyIfAbsent  如果当前位置已存在一个值,是否替换,false是替换,true是不替换* @param evict  表是否在创建模式,如果为false,则表是在创建模式。*/final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict)

下面的一张图简单解释了putVal方法的作用

在这里插入图片描述

我将这个过程分为了7步,分别是:

1、检查table是否为空,如果为空就初始化

2.检查table中位置为(n -1 ) & hash 是否为空,如果为空,直接放入(这是放在数组里)

3.如果桶中存在的元素的key和hash都相等,直接覆盖旧value

4.判断存放该元素的链表是否转为红黑树,如果为红黑树,直接插入,此时上面3是不成立,hash值不相等,也就是key值不等(hash值是由key算出来的)

5.第3和第4都不成立,将插入元素存放在链表中(也有可能是红黑树)

6.存在key值和hash值相等的,直接覆盖旧value

7.将记录修改次数加1,判断是否需要扩容,如果需要就扩容

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K, V>[] tab;Node<K, V> p;int n, i;//1、检查table是否为空,如果为空就初始化if ((tab = table) == null || (n = tab.length) == 0)//  初始化,也是扩容n = (tab = resize()).length;//2.检查table中位置为(n -1 ) & hash 是否为空,如果为空,直接放入(这是放在数组里)if ((p = tab[i = (n - 1) & hash]) == null)//放入tab[i] = newNode(hash, key, value, null);//桶中已经存在元素了,也就是说 table中( n -1) & hash这个位置不为空(发生碰撞了)else {Node<K, V> e;K k;//3.如果桶中存在的元素的key和hash都相等,直接覆盖旧valueif (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;//4.判断存放该元素的链表是否转为红黑树,如果为红黑树,直接插入,此时上面3是不成立,hash值不相等,也就是key值不等(hash值是由key算出来的)else if (p instanceof TreeNode)//存放在红黑树里e = ((TreeNode<K, V>) p).putTreeVal(this, tab, hash, key, value);//5.第3和第4都不成立,将插入元素存放在链表中else {//循环链表,找到链表末尾插入元素for (int binCount = 0; ; ++binCount) {if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);//判断当前链表的元素是否超过要转换为红黑树的阈值 (节点数超过8并且数组长度超过64就要转换为红黑树)if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st//转换为红黑树存储treeifyBin(tab, hash);break;}//遍历链表,看链表中是否存在hash和key与要插入进来的元素相同,如果相同,跳出循环。if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))//跳出循环break;// 跟 e = p.next 组成用来遍历链表。p = e;}}//6.存在key值和hash值相等的,直接覆盖旧valueif (e != null) { // existing mapping for key//取出e的valueV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)//覆盖e.value = value;//访问后回调afterNodeAccess(e);return oldValue;}}//7.将记录修改次数加1,判断是否需要扩容,如果需要就扩容++modCount;if (++size > threshold)resize();//插入后回调afterNodeInsertion(evict);return null;}

这里借助一张图片更容易理解

在这里插入图片描述
图片来自这里,觉得图片更容易看懂这个方法工作的流程。


http://chatgpt.dhexx.cn/article/vPajysc0.shtml

相关文章

org.hibernate.Session.evict(Object object)方法的使用

在一个实体A、B的关联关系中&#xff0c;如下图&#xff1a; B外键关联A&#xff0c;关联字段A_id A中保存有B的集合blist 在A的实体属性blist&#xff0c;使用懒加载注解&#xff0c;如下: OneToMany(targetEntityB.class, cascade CascadeType.ALL, fetch FetchType.LAZY)…

mysql evict_Hibernate的flush()和evict()

/** * 测试uuid主键生成策略 */ public void testSave1() { Session session null; Transaction tx null; try { session HibernateUtils.getSession(); tx session.beginTransaction(); User1 user new User1(); user.setName("李四"); user.setPassword("…

Ceph Cache Tier中flush和evict机制源码分析

存储系统&#xff1a;ceph-14.2.22 操作系统&#xff1a;ubuntu-server-16.04.07 OSDService::agent_entry [ ceph/src/osd/OSD.cc ] OSD服务启动过程中会创建一个名为osd_srv_agent的线程&#xff0c;在分层存储中&#xff0c;该线程负责缓存池与数据池之间的数据迁移工作。该…

HashMap evict 放逐之旅

HashMap evict 放逐之旅 我不认识的evict小结 我不认识的evict 正在撸猫写代码的我&#xff0c;遇到了一个LinkedHashMap ConcurrentModifyException&#xff0c;真是让人头秃。问题排查过程也是费了一些力气&#xff08;手动狗头&#xff09;&#xff0c;最后发现是我异步请求…

Redis源码剖析之内存淘汰策略(Evict)

文章目录 何为Evict如何EvictRedis中的Evict策略源码剖析LRU具体实现LFU具体实现LFU计数器增长LFU计数器衰减 evict执行过程evict何时执行evict.c 总结 Redis作为一个成熟的数据存储中间件&#xff0c;它提供了完善的数据管理功能&#xff0c;比如之前我们提到过的 数据过期和…

WiredTiger系列2:Eviction详解

Eviction Evict的实质主要是将内存中的page淘汰出内存&#xff0c;简单来说&#xff0c;当cache里面的“脏页”达到一定比例或cache使用量达到一定比例时&#xff0c;wt就会触发相应的evict page线程来将pages&#xff08;包含干净的pages和脏pages&#xff09;按一定的算法&a…

onload事件

onload事件&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><script type"text/javascript">//onload事件的方法function onloadFun(){alert(静态注…

onUnload事件

1. 首先JavaScript会使我们有能力创建动态页面然后JavaScript是可以被侦测到事件行为的然而在网页中的每一个元素都将可以来产生某些可以触发JavaScript的函数的事件就可以打个比方说我们在用户中里面点击某个按钮时的产生的某一个onClick 事件来触发某个函数之后就在事件中在H…

script标签的onload事件的触发时机

onload事件在资源被加载完成后会被触发。对于script标签&#xff0c;在外部js文件被加载后代码会被立即执行。那么&#xff0c;外部js文件中的代码和该script标签的onload回调函数&#xff0c;它们的执行顺序是怎样的呢&#xff1f;没有找到官方的说明文档&#xff0c;所以自己…

load事件

javaScript中最常用到的一个事件就是load。当页面完全加载后&#xff08;包括所有图像、javaScript文件、css文件等外部资源&#xff09;&#xff0c;就会触发window上边的load事件。 window&#xff1a; window.addEventListener(load, function(e) {console.log(页面完全加…

onload 和 onunload 事件

onload 和 onunload 事件会在用户进入或离开页面时被触发。onload 事件可用于检测访问者的浏览器类型和浏览器版本&#xff0c;并基于这些信息来加载网页的正确版本。onload 和 onunload 事件可用于处理 cookie。 onmousedown,onmouseup 以及 onclick 构成了鼠标点击事件的所有…

window的onload事件的用法

1.最简单的用法 注&#xff1a;奇葩&#xff0c;我没用过 2.在JS语句调用&#xff08;正确使用姿势&#xff09; 或使用jquery onload 事件会在页面或图像加载完成后立即发生。 3.window.onload()的加载问题 由于HTML加载时由上往下的&#xff0c;在HTML加载的时候&#…

JS中window.onload事件详解

window.onload出现的原因&#xff1f;  我们都知道页面的代码顺序是从上往下进行加载&#xff0c;很多时候我们要对页面中的某一个模块进行操作&#xff0c;这时候我们常常使用javascript代码来进行操作。为了能够保证操作的模块或对象在js代码之前就加载了&#xff0c;我们不…

浏览器的onload事件

如下代码&#xff0c;因为代码从上到下执行&#xff0c;btn节点还未创建好就去获取会报错 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge&q…

JavaScript的window.onload事件的理解

window.onload()的作用 window.onload() 方法用于在网页加载完毕后立刻执行的操作&#xff0c;即当 HTML 文档加载完毕后&#xff0c;立刻执行某个方法。window.onload() 通常用于 元素&#xff0c;在页面完全载入后(包括图片、css文件等等)执行脚本代码。 只有一个要执行的函…

I2C协议——I2C框图和I2C通信过程

1.软件模拟和硬件模拟的概念 所谓软件模拟&#xff0c;即直接使用 CPU 内核按照 I2C 协议的要求控制 GPIO 输出高低电平。如控制产生 I2C 的起始信号时&#xff0c;先控制作为 SCL 线的 GPIO 引脚输出高电平&#xff0c;然后控制作为 SDA 线的 GPIO 引脚在此期间完成由高电平至…

通信协议——I2C协议/IIC协议解析

目录 I2C协议概述 I2C通信原理 I2C通信时序 I2C协议概述 同步通信 半双工&#xff08;分时&#xff09; 串行传输 电平信号 特点&#xff1a;①有两根传输线&#xff08;时钟线SCL、双向数据线SDA&#xff09; ②主从模式&#xff1a;通信双方为主设备&#xff08;Master&…

I2C基础

I2C基础 1 基本介绍2 特点3 硬件连接4 通信4.1 控制器4.2 协议 5 SPI VS I2C 1 基本介绍 IC (Inter-Integrated Circuit)。内部集成电路。拥有两根线&#xff0c;一根数据线SDA和一根时钟线SCL。 这两条线都是漏极开路或者集电极开路结构&#xff0c;使用时需要外加上拉电阻&a…

I2C总线协议

1. 简介 I2C (Inter-Integrated Circuit&#xff09;&#xff0c;是一种串行通信总线&#xff0c;用于连接微控制器及其外围设备&#xff0c;实现主控制器和从器件间的主从双向通信&#xff0c;是一种同步半双工通信(两端时钟频率一致&#xff0c;双向通信&#xff0c;但不能同…

I2C协议最细致的讲解

I2C通讯协议(Inter—lntegrated Circuit)是由Phiilps公司开发的&#xff0c;由于它引脚少&#xff0c;硬件实现简单&#xff0c;可扩展性强&#xff0c;不需要USART、CAN等通讯协议的外部收发设备&#xff0c;现在被广泛地使用在系统内多个集成电路(IC)间的通讯。 I2C物理层的特…