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 开发的核心语言
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 【热…...
 
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
 
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
 
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
 
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
 
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
 
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
 
从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
