Java putIfAbsent() 详解
Java putIfAbsent()
方法详解
在 Java 中,putIfAbsent()
是 Map
接口中的一个方法,从 Java 8 开始引入。它用于向映射中添加一个键值对,只有在该键尚未存在时才进行添加操作。如果键已存在,则不会覆盖原有值。
1. 方法定义
方法签名
default V putIfAbsent(K key, V value)
参数
key
:要插入的键。value
:与键关联的值。
返回值
- 如果键不存在,插入后返回
null
。 - 如果键已存在,则返回该键当前的值,插入操作不会执行。
2. 功能描述
-
检查键是否存在:
- 如果键不存在,则将键值对插入到映射中。
- 如果键已存在,则保持原有键值对不变。
-
线程安全:
- 对于并发映射(如
ConcurrentHashMap
),putIfAbsent()
是线程安全的,保证了原子性。 - 对于普通
HashMap
,则不是线程安全的。
- 对于并发映射(如
-
避免覆盖现有值:
- 与直接调用
put()
不同,putIfAbsent()
不会覆盖现有的值。
- 与直接调用
3. 示例代码
3.1 基本用法
import java.util.HashMap;
import java.util.Map;public class PutIfAbsentExample {public static void main(String[] args) {Map<String, String> map = new HashMap<>();// 初始插入map.put("A", "Apple");// 插入新键map.putIfAbsent("B", "Banana");System.out.println(map); // 输出:{A=Apple, B=Banana}// 尝试插入已存在的键map.putIfAbsent("A", "Avocado");System.out.println(map); // 输出:{A=Apple, B=Banana}}
}
分析:
- 初次插入键
A
和B
。 - 对于键
A
,putIfAbsent()
不会覆盖原值,因此保持不变。
3.2 结合返回值
import java.util.HashMap;
import java.util.Map;public class PutIfAbsentReturnExample {public static void main(String[] args) {Map<String, String> map = new HashMap<>();// 尝试插入新键String result1 = map.putIfAbsent("C", "Cat");System.out.println(result1); // 输出:null(键 "C" 不存在)// 再次尝试插入相同键String result2 = map.putIfAbsent("C", "Carrot");System.out.println(result2); // 输出:Cat(键 "C" 已存在,值保持为 "Cat")System.out.println(map); // 输出:{C=Cat}}
}
3.3 使用 ConcurrentHashMap
putIfAbsent()
在 ConcurrentHashMap
中非常有用,可以实现线程安全的惰性初始化。
import java.util.concurrent.ConcurrentHashMap;public class ConcurrentPutIfAbsent {public static void main(String[] args) {ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();// 多线程同时尝试插入map.putIfAbsent("key", 1);map.putIfAbsent("key", 2);System.out.println(map); // 输出:{key=1}(只插入一次)}
}
4. putIfAbsent()
和 put()
的区别
特性 | put() | putIfAbsent() |
---|---|---|
覆盖值 | 如果键已存在,则覆盖旧值。 | 如果键已存在,则不覆盖旧值。 |
返回值 | 返回旧值(如果存在),否则返回 null 。 | 如果键已存在,返回旧值,否则返回 null 。 |
性能 | 直接插入操作,可能覆盖原值。 | 需要额外检查键是否存在(线程安全时也加锁)。 |
线程安全(ConcurrentMap) | 不是线程安全的,需要额外同步。 | 线程安全,尤其适用于 ConcurrentHashMap 。 |
5. 使用场景
5.1 避免覆盖已存在值
当希望保持某个键的初始值,避免被后续操作覆盖时:
map.putIfAbsent("key", "initialValue");
5.2 延迟初始化
在多线程环境中,putIfAbsent()
可以安全地初始化共享资源:
public static ConcurrentHashMap<String, String> cache = new ConcurrentHashMap<>();public static String getValue(String key) {return cache.putIfAbsent(key, "DefaultValue");
}
5.3 统计或计数
可以用 putIfAbsent()
初始化键的默认值,用于统计场景:
map.putIfAbsent("count", 0);
map.put("count", map.get("count") + 1);
6. 注意事项
-
线程安全
- 对普通的
HashMap
使用putIfAbsent()
并不能实现线程安全。 - 如果需要线程安全,请使用
ConcurrentHashMap
或其他并发集合。
- 对普通的
-
返回值的使用
- 返回值可以用来判断键是否已存在,从而决定后续操作。
-
性能开销
- 对于并发集合(如
ConcurrentHashMap
),putIfAbsent()
内部使用了锁来保证原子性,可能有一定性能开销。
- 对于并发集合(如
-
不可用于
null
值putIfAbsent()
不允许插入null
值,ConcurrentHashMap
会抛出NullPointerException
。
7. 总结
putIfAbsent()
是一种安全的插入操作:- 如果键不存在,则插入键值对。
- 如果键已存在,则保持原值不变。
- 线程安全性:
- 在
ConcurrentHashMap
中,putIfAbsent()
是线程安全的,可用于多线程环境。
- 在
- 适用场景:
- 避免值覆盖。
- 延迟初始化或缓存加载。
- 实现统计或计数。
通过正确使用 putIfAbsent()
方法,可以简化代码逻辑,同时确保数据的完整性和安全性,尤其在并发场景中非常实用。
相关文章:
Java putIfAbsent() 详解
Java putIfAbsent() 方法详解 在 Java 中,putIfAbsent() 是 Map 接口中的一个方法,从 Java 8 开始引入。它用于向映射中添加一个键值对,只有在该键尚未存在时才进行添加操作。如果键已存在,则不会覆盖原有值。 1. 方法定义 方法…...

使用PSpice进行第一个电路的仿真
1、单击【开始】菜单,选择【OrCAD Capture CIS Lite】。 2、单击【File】>【New】>【Project】。 3、①填入Name下面的文本框(提示:项目名称不要出现汉字); ②选择【Analog or Mixed A/D】; ③单击【…...

路漫漫其修远兮,吾将上下而求索---第一次使用github的过程记录和个人感受
文章目录 1.仓库位置2.新建仓库3.配置仓库4.克隆和上传5.推荐文章和我的感受 1.仓库位置 这个仓库的位置就是在我们的这个个人主页的右上角;如果是第一次注册账号的话,这个主页里面肯定是不存在仓库的,需要我们自己手动的进行创建࿱…...

【微软:多模态基础模型】(4)统一视觉模型
欢迎关注[【youcans的AGI学习笔记】](https://blog.csdn.net/youcans/category_12244543.html)原创作品 【微软:多模态基础模型】(1)从专家到通用助手 【微软:多模态基础模型】(2)视觉理解 【微…...
GRS码(Generalized Reed-Solomon Code)
定义: 令 k ≤ n ≤ q k\le n\le q k≤n≤q, α ∈ F q n \alpha\in\mathbb{F}_q^n α∈Fqn是n元组( α ( α 1 , . . . , α n ) , α i ≠ α j , ∀ i ≠ j ∈ { 1 , . . . , n } \alpha(\alpha_1,...,\alpha_n),\alpha_i\ne \alpha_j,…...

三、谷粒商城- Spring Cloud Alibaba(3)
🌻🌻 目录 🌻🌻 一、SpringCloud Alibaba1.1、SpringCloud Alibaba 简介1.2、SpringCloud Alibaba-Nacos[作为注册中心]1.2.1 将微服务注册到 nacos 中1.2.2 服务注册到 nacos,远程调用 1.3、SpringCloud Alibaba-Naco…...
MATLAB和Python激发光谱
激发光谱是一种用于研究物质发光特性的分析方法。当样品吸收特定波长的光时,电子从基态跃迁至激发态。随后,当电子返回基态时,会发射出光子,产生荧光或磷光。激发光谱通过测量不同波长的入射光激发下的发光强度来获取数据。该技术…...

学习笔记024——Ubuntu 安装 Redis遇到相关问题
目录 1、更新APT存储库缓存: 2、apt安装Redis: 3、如何查看检查 Redis版本: 4、配置文件相关设置: 5、重启服务,配置生效: 6、查看服务状态: 1、更新APT存储库缓存: sudo apt…...

UE5 腿部IK 解决方案 footplacement
UE5系列文章目录 文章目录 UE5系列文章目录前言一、FootPlacement 是什么?二、具体实现 前言 在Unreal Engine 5 (UE5) 中,腿部IK(Inverse Kinematics,逆向运动学)是一个重要的动画技术,用于实现角色脚部准…...

北航软件算法C4--图部分
C4上级图部分 TOPO!步骤代码段TOPO排序部分 完整代码 简单的图图题目描述输入输出样例步骤代码段开辟vector容器作为dist二维数组初始化调用Floyd算法查询 完整代码 负环题目描述输入输出样例步骤代码段全局变量定义spfa1函数用于判断是否有负环spfa2用于记录每个点到1号点的距…...

PCL点云开发-解决在Qt中嵌入点云窗口出现的一闪而过的黑窗口
PCL点云开发-解决在Qt中嵌入点云窗口出现的一闪而过的黑窗口 众所周知,在windows下开发PCL点云最快的方式就是到官网下载其预编译好的库,比如: PCL-1.14.0-AllInOne-msvc2022-win64.exe 这时候你到网络上搜索,大概率会有两种方案…...

本地音乐服务器(二)
4. 上传音乐模块设计 4.1 上传音乐的接口设计 请求和响应设计: 新建music实体类: Data public class Music {private int id;private String title;private String singer;private String time;private String url;private int userid; } 4.2 创建Mu…...

第三十六篇——伯努利试验:到底如何理解随机性?
目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么? 四、总结五、升华 一、背景介绍 概率论指导着我们对于直觉不靠谱的事情,以及为我们如何更高效…...

【Android、IOS、Flutter、鸿蒙、ReactNative 】屏幕适配
Android Java 屏幕适配 参考 今日头条适配依赖配置 添加设计屏幕尺寸 设置字体大小 通过切换不同屏幕尺寸查看字体大小 设置文本宽高 通过切换不同屏幕尺寸查看文本宽高 Android Compose 屏幕适配 <...

candence : 如何利用EXCEL 绘制复杂、多管脚元件
如何利用EXCEL 绘制复杂、多管脚元件 前面的步骤直接略过 我们以STM32F407VEXX 系列 100pin 芯片为例讲解: 1、新建好一个空元件 2、使用阵列,放置管脚 点击 “ ok ” 3、选中所有管脚 右键 “edit properites” 出现如下页面 4、点击 左上角&…...
项目配置文件选择(Json,xml,Yaml, INI)
选择使用哪种类型的配置文件(如 JSON、XML 或其他格式)取决于多个因素,包括项目的需求、团队的熟悉程度、数据结构的复杂性以及可读性和可维护性等。以下是对常见配置文件格式的比较,以及在不同情况下的推荐: 1. JSON&…...
Android 使用Retrofit 以纯二进制文件流上传文件
一、背景 一般上传文件都是以表单形式上传文件,最近项目中涉及到非表单形式上传文件流,分为单个文件流上传、大文件分段上传,此种情景资料较少,这里记录下。 二、方案介绍 2.1 需求协议 1. 上传文件 API 端点:/serv…...

Vue3踩坑记录
目录 一、定义常变量 1.1、ref和reactive到底用谁? 二、双向绑定 2.1、直接改变表格该行数据 2.1、在弹窗改变表格该行数据 一、定义常变量 1.1、ref和reactive到底用谁? 已知:使用ref定义基础类型数据;使用reactive定义复…...

大数据-227 离线数仓 - Flume 自定义拦截器(续接上节) 采集启动日志和事件日志
点一下关注吧!!!非常感谢!!持续更新!!! Java篇开始了! 目前开始更新 MyBatis,一起深入浅出! 目前已经更新到了: Hadoop࿰…...

【热门主题】000054 ECMAScript:现代 Web 开发的核心语言
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 【热…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...

1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...

SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...