当前位置: 首页 > news >正文

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}}
}

分析

  1. 初次插入键 AB
  2. 对于键 AputIfAbsent() 不会覆盖原值,因此保持不变。

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. 注意事项

  1. 线程安全

    • 对普通的 HashMap 使用 putIfAbsent() 并不能实现线程安全。
    • 如果需要线程安全,请使用 ConcurrentHashMap 或其他并发集合。
  2. 返回值的使用

    • 返回值可以用来判断键是否已存在,从而决定后续操作。
  3. 性能开销

    • 对于并发集合(如 ConcurrentHashMap),putIfAbsent() 内部使用了锁来保证原子性,可能有一定性能开销。
  4. 不可用于 null

    • putIfAbsent() 不允许插入 null 值,ConcurrentHashMap 会抛出 NullPointerException

7. 总结

  • putIfAbsent() 是一种安全的插入操作
    • 如果键不存在,则插入键值对。
    • 如果键已存在,则保持原值不变。
  • 线程安全性
    • ConcurrentHashMap 中,putIfAbsent() 是线程安全的,可用于多线程环境。
  • 适用场景
    • 避免值覆盖。
    • 延迟初始化或缓存加载。
    • 实现统计或计数。

通过正确使用 putIfAbsent() 方法,可以简化代码逻辑,同时确保数据的完整性和安全性,尤其在并发场景中非常实用。

相关文章:

Java putIfAbsent() 详解

Java putIfAbsent() 方法详解 在 Java 中&#xff0c;putIfAbsent() 是 Map 接口中的一个方法&#xff0c;从 Java 8 开始引入。它用于向映射中添加一个键值对&#xff0c;只有在该键尚未存在时才进行添加操作。如果键已存在&#xff0c;则不会覆盖原有值。 1. 方法定义 方法…...

使用PSpice进行第一个电路的仿真

1、单击【开始】菜单&#xff0c;选择【OrCAD Capture CIS Lite】。 2、单击【File】>【New】>【Project】。 3、①填入Name下面的文本框&#xff08;提示&#xff1a;项目名称不要出现汉字&#xff09;&#xff1b; ②选择【Analog or Mixed A/D】&#xff1b; ③单击【…...

路漫漫其修远兮,吾将上下而求索---第一次使用github的过程记录和个人感受

文章目录 1.仓库位置2.新建仓库3.配置仓库4.克隆和上传5.推荐文章和我的感受 1.仓库位置 这个仓库的位置就是在我们的这个个人主页的右上角&#xff1b;如果是第一次注册账号的话&#xff0c;这个主页里面肯定是不存在仓库的&#xff0c;需要我们自己手动的进行创建&#xff1…...

【微软:多模态基础模型】(4)统一视觉模型

欢迎关注[【youcans的AGI学习笔记】](https://blog.csdn.net/youcans/category_12244543.html&#xff09;原创作品 【微软&#xff1a;多模态基础模型】&#xff08;1&#xff09;从专家到通用助手 【微软&#xff1a;多模态基础模型】&#xff08;2&#xff09;视觉理解 【微…...

GRS码(Generalized Reed-Solomon Code)

定义&#xff1a; 令 k ≤ n ≤ q k\le n\le q k≤n≤q&#xff0c; α ∈ F q n \alpha\in\mathbb{F}_q^n α∈Fqn​是n元组&#xff08; α ( α 1 , . . . , α n ) , α i ≠ α j , ∀ i ≠ j ∈ { 1 , . . . , n } \alpha(\alpha_1,...,\alpha_n),\alpha_i\ne \alpha_j,…...

三、谷粒商城- Spring Cloud Alibaba(3)

&#x1f33b;&#x1f33b; 目录 &#x1f33b;&#x1f33b; 一、SpringCloud Alibaba1.1、SpringCloud Alibaba 简介1.2、SpringCloud Alibaba-Nacos[作为注册中心]1.2.1 将微服务注册到 nacos 中1.2.2 服务注册到 nacos&#xff0c;远程调用 1.3、SpringCloud Alibaba-Naco…...

MATLAB和Python激发光谱

激发光谱是一种用于研究物质发光特性的分析方法。当样品吸收特定波长的光时&#xff0c;电子从基态跃迁至激发态。随后&#xff0c;当电子返回基态时&#xff0c;会发射出光子&#xff0c;产生荧光或磷光。激发光谱通过测量不同波长的入射光激发下的发光强度来获取数据。该技术…...

学习笔记024——Ubuntu 安装 Redis遇到相关问题

目录 1、更新APT存储库缓存&#xff1a; 2、apt安装Redis&#xff1a; 3、如何查看检查 Redis版本&#xff1a; 4、配置文件相关设置&#xff1a; 5、重启服务&#xff0c;配置生效&#xff1a; 6、查看服务状态&#xff1a; 1、更新APT存储库缓存&#xff1a; sudo apt…...

UE5 腿部IK 解决方案 footplacement

UE5系列文章目录 文章目录 UE5系列文章目录前言一、FootPlacement 是什么&#xff1f;二、具体实现 前言 在Unreal Engine 5 (UE5) 中&#xff0c;腿部IK&#xff08;Inverse Kinematics&#xff0c;逆向运动学&#xff09;是一个重要的动画技术&#xff0c;用于实现角色脚部准…...

北航软件算法C4--图部分

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

PCL点云开发-解决在Qt中嵌入点云窗口出现的一闪而过的黑窗口

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

本地音乐服务器(二)

4. 上传音乐模块设计 4.1 上传音乐的接口设计 请求和响应设计&#xff1a; 新建music实体类&#xff1a; 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.通过这篇文章结合我知道的东西我能想到什么&#xff1f; 四、总结五、升华 一、背景介绍 概率论指导着我们对于直觉不靠谱的事情&#xff0c;以及为我们如何更高效…...

【Android、IOS、Flutter、鸿蒙、ReactNative 】屏幕适配

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

candence : 如何利用EXCEL 绘制复杂、多管脚元件

如何利用EXCEL 绘制复杂、多管脚元件 前面的步骤直接略过 我们以STM32F407VEXX 系列 100pin 芯片为例讲解&#xff1a; 1、新建好一个空元件 2、使用阵列&#xff0c;放置管脚 点击 “ ok ” 3、选中所有管脚 右键 “edit properites” 出现如下页面 4、点击 左上角&…...

项目配置文件选择(Json,xml,Yaml, INI)

选择使用哪种类型的配置文件&#xff08;如 JSON、XML 或其他格式&#xff09;取决于多个因素&#xff0c;包括项目的需求、团队的熟悉程度、数据结构的复杂性以及可读性和可维护性等。以下是对常见配置文件格式的比较&#xff0c;以及在不同情况下的推荐&#xff1a; 1. JSON&…...

Android 使用Retrofit 以纯二进制文件流上传文件

一、背景 一般上传文件都是以表单形式上传文件&#xff0c;最近项目中涉及到非表单形式上传文件流&#xff0c;分为单个文件流上传、大文件分段上传&#xff0c;此种情景资料较少&#xff0c;这里记录下。 二、方案介绍 2.1 需求协议 1. 上传文件 API 端点&#xff1a;/serv…...

Vue3踩坑记录

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

大数据-227 离线数仓 - Flume 自定义拦截器(续接上节) 采集启动日志和事件日志

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; Java篇开始了&#xff01; 目前开始更新 MyBatis&#xff0c;一起深入浅出&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff0…...

【热门主题】000054 ECMAScript:现代 Web 开发的核心语言

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 【热…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

PostgreSQL——环境搭建

一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在&#xff0…...

高考志愿填报管理系统---开发介绍

高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发&#xff0c;采用现代化的Web技术&#xff0c;为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## &#x1f4cb; 系统概述 ### &#x1f3af; 系统定…...

解析两阶段提交与三阶段提交的核心差异及MySQL实现方案

引言 在分布式系统的事务处理中&#xff0c;如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议&#xff08;2PC&#xff09;通过准备阶段与提交阶段的协调机制&#xff0c;以同步决策模式确保事务原子性。其改进版本三阶段提交协议&#xff08;3PC&#xf…...

QT开发技术【ffmpeg + QAudioOutput】音乐播放器

一、 介绍 使用ffmpeg 4.2.2 在数字化浪潮席卷全球的当下&#xff0c;音视频内容犹如璀璨繁星&#xff0c;点亮了人们的生活与工作。从短视频平台上令人捧腹的搞笑视频&#xff0c;到在线课堂中知识渊博的专家授课&#xff0c;再到影视平台上扣人心弦的高清大片&#xff0c;音…...