Java Collection API增强功能系列之二 List.of、Set.of、Map.of

Java 9集合工厂方法:用List.ofSet.ofMap.of创建安全不可变集合

Java 9引入了革命性的集合工厂方法List.ofSet.ofMap.of,彻底改变了开发者创建小型不可变集合的方式。这些方法不仅语法简洁,还在安全性和性能上实现了质的飞跃。本文将深入解析这些工厂方法的核心特性,并通过对比传统方式,展示其在实际开发中的优势。


一、新工厂方法概览

1. 方法家族

方法签名说明示例
List.of(E... elements)创建不可变ListList<String> list = List.of("A", "B");
Set.of(E... elements)创建不可变Set(元素唯一)Set<Integer> set = Set.of(1, 2, 3);
Map.of(K k1, V v1, ...)创建不可变Map(最多10个键值对)Map<String, Integer> map = Map.of("a", 1, "b", 2);
Map.ofEntries(Map.Entry...)创建任意数量键值对的MapMap.ofEntries(entry("a", 1), entry("b", 2))

二、核心优势

1. 真正不可变性(vs 伪不可变)

传统方式的问题

// Java 8的"不可变"集合
List<String> oldList = Collections.unmodifiableList(new ArrayList<>(Arrays.asList("A", "B"))
);
oldList.add("C"); // 运行时抛出UnsupportedOperationException

新方式

List<String> newList = List.of("A", "B");
newList.add("C"); // 编译期即可通过IDE提示发现问题
特性新工厂方法Collections.unmodifiableList
编译期类型检查✅ 直接拒绝修改操作❌ 运行时异常
防御原集合修改✅ 完全独立❌ 包装集合仍受原集合影响

2. 空值安全(Null Safety)

List.of("A", null); // 立即抛出NullPointerException
Set.of(null);       // 同上
Map.of("key", null);// 值也不能为null

设计哲学:在集合创建时严格拒绝null,避免后续NPE隐患。

3. 元素唯一性保证(针对Set/Map)

Set.of(1, 1); // 直接抛出IllegalArgumentException
Map.of("a", 1, "a", 2); // 键重复,抛出异常

4. 性能优化

JVM针对工厂方法返回的集合做了深度优化:

  • 内存占用:比new ArrayList节省约30%内存
  • 迭代速度:比传统集合快2-3倍(得益于紧凑存储)
  • 哈希计算Set.of/Map.of在创建时预计算哈希值

三、与传统方式对比

1. 创建不可变List

Java 8方式

List<String> list = Collections.unmodifiableList(new ArrayList<>(Arrays.asList("A", "B"))
);
// 需要两层包装,内存开销大

Java 9方式

List<String> list = List.of("A", "B");
// 直接返回优化后的不可变实例

2. 创建不可变Set

传统方式

Set<Integer> set = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(1, 2, 3))
);
// 无法保证初始化时的元素唯一性

新方式

Set<Integer> set = Set.of(1, 2, 3);
// 自动检查元素唯一性,发现重复立即报错

3. 创建不可变Map

传统方式

Map<String, Integer> tempMap = new HashMap<>();
tempMap.put("a", 1);
tempMap.put("b", 2);
Map<String, Integer> map = Collections.unmodifiableMap(tempMap);
// 需要中间变量,存在竞态条件风险

新方式

Map<String, Integer> map = Map.of("a", 1, "b", 2);
// 线程安全,无中间状态

四、使用注意事项

1. 元素限制

  • 数量限制Map.of最多接受10个键值对(超过需用Map.ofEntries
  • 类型限制:不支持基本类型(需用包装类)
    List.of(1, 2, 3);      // 正确:自动装箱
    List.of(new int[]{1}); // 错误:实际类型为List<int[]>
    

2. 防御性编程

// 接收外部集合时创建防御副本
void process(List<String> input) {List<String> safeList = List.copyOf(input); // Java 10+// 或 List<String> safeList = List.of(input.toArray());
}

3. 与Stream API结合

// 过滤后生成不可变集合
List<String> filtered = Stream.of("A", "B", "C").filter(s -> s.length() > 1).collect(Collectors.toUnmodifiableList());

五、最佳实践场景

1. 配置参数存储

private static final Set<String> VALID_STATUSES = Set.of("NEW", "PROCESSING", "COMPLETED");

2. 测试数据构造

@Test
void testSort() {List<Integer> numbers = List.of(3, 1, 4);Collections.sort(numbers); // 立即抛出UnsupportedOperationException
}

3. 返回值保护

public List<Employee> getEmployees() {return List.copyOf(internalList); // 返回不可变副本
}

六、常见问题解答

Q1:为什么需要新的工厂方法?

  • 类型安全:编译时即可发现修改操作
  • 性能优势:专用实现比通用集合更高效
  • 语义清晰:明确表达不可变意图

Q2:如何创建空集合?

List<String> emptyList = List.of(); // 空集合单例
Set<Integer> emptySet = Set.of();
Map<String, String> emptyMap = Map.of();

Q3:与Arrays.asList的区别?

特性List.ofArrays.asList
可变性完全不可变半可变(可set不可add)
空值支持❌ 禁止null✅ 允许null
与原数组关联❌ 独立存储✅ 共享底层数组
内存占用优化后的紧凑结构包装器+数组引用

七、总结

使用新工厂方法的三大理由

  1. 🛡️ 安全性:杜绝意外修改,强化空值约束
  2. 🚀 性能:专为不可变场景优化,内存效率更高
  3. 简洁性:一行代码表达创建不可变集合的意图

适用原则

  • 优先用于静态配置数据
  • 推荐作为方法返回值防止外部修改
  • 适合存储需要确保完整性的业务数据

迁移建议

  • 逐步替换项目中Collections.unmodifiableXXX的用法
  • 在单元测试中优先采用新语法
  • 注意检查历史代码中的null值使用

Java 9的集合工厂方法不仅是语法糖,更是工程实践的重要进步。合理运用这些特性,可以让代码更健壮、更高效,同时降低维护成本。

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

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

相关文章

网络通信微服务

网络通信 VPN 服务器分配内网 IP&#xff0c;加密所有流量,以使用外网访问内网资源 使用了VPN只是第一关&#xff0c;只进入了人家的大厅&#xff0c;只可以访问公共服务&#xff08;像是只可以在人间公司的大厅里溜达&#xff09;&#xff0c;若想要访问人家提供的高级服务&a…

arm之s3c2440的I2C的用法

基础概念 IC&#xff08;Inter-Integrated Circuit&#xff09;又称I2C&#xff0c;是是IICBus简称&#xff0c;所以中文应该叫集成电路总线。 IIC的总线的使用场景&#xff0c;所有挂载在IIC总线上的设备都有两根信号线&#xff0c;一根是数据线SDA&#xff0c;另一 根是时钟…

算法 | 蜣螂优化算法原理,引言,公式,算法改进综述,应用场景及matlab完整代码

蜣螂优化算法(Dung Beetle Optimizer, DBO)详解 1. 算法原理 蜣螂优化算法(DBO)是一种基于自然界蜣螂行为的元启发式优化算法,灵感来源于蜣螂的滚球、繁殖、觅食和偷窃行为。其核心思想是通过模拟蜣螂在复杂环境中的协作与竞争机制,解决全局优化问题。关键行为模拟: 滚球…

uniapp开发实战自定义组件形式实现自定义海报功能

在 UniApp 中实现自定义海报功能,可以通过 Canvas 来绘制海报。Canvas 提供了丰富的绘图 API,可以精确控制文字、图片和二维码的位置。下面是一个完整的示例,展示如何创建一个自定义海报组件。 项目结构 假设你的项目结构如下: project-root/ ├── pages/ │ └──…

dockerfile构建镜像方式

在 Docker 中&#xff0c;可使用 docker build 命令依据 Dockerfile 构建镜像。下面为你详细介绍构建镜像的具体方式。 基本构建命令 若要构建镜像&#xff0c;需在包含 Dockerfile 的目录下执行 docker build 命令。基本语法如下&#xff1a; bash docker build -t <镜像…

STM32F103_LL库+寄存器学习笔记10 - DMA传输过半+DMA传输完成中断实现DMA串口接收“双缓冲“

导言 《[[STM32F103_LL库寄存器学习笔记09 - DMA串口接收与DMA串口发送&#xff0c;串口接收空闲中断]]》上一章节完成DMA发送与接收。此时&#xff0c;有一个致命的问题可能会导致数据包丢失。原因是USART1接收只开启了接收空闲中断(IDLE)&#xff0c;DMA在连续模式下&#xf…

李宏毅机器学习笔记06 | 鱼和熊掌可以兼得的机器学习 - 内容接宝可梦

本章提要 深度学习可以在较少参数量的情况下得到比较低的loss&#xff1a; h a l l a r g min ⁡ h ∈ H L ( h , D a l l ) h^{all}arg \min_{h \in H}L(h,D_{all}) hallargminh∈H​L(h,Dall​) 引入 如何权衡模型的复杂程度 Tradeoff of Model Complexity 理论上&#…

java八股文之JVM

1.什么是程序计数器 程序计数器是 JVM 管理线程执行的“定位器”&#xff0c;记录每个线程当前执行的指令位置&#xff0c;确保程序流程的连续性和线程切换的准确性。线程私有的&#xff0c;每个线程一份&#xff0c;内部保存的字节码的行号。用于记录正在执行的字节码指令的地…

Android设计模式之观察者模式

一、定义&#xff1a;定义对象间一种一对多的依赖关系&#xff0c;使得每当一个对象改变状态&#xff0c;则所有依赖于它的对象都会得到通知并被自动更新。 二、核心角色&#xff1a; Subject&#xff1a;抽象主题被观察的角色&#xff0c;管理观察者集合&#xff0c;提供注册…

海康gdb流程

gdb相关 在initrun.sh文件里加入&#xff0c;注意需要在hikauto起来之前 # 设置core dump大小 ulimit -c unlimited if [ $? -eq 0 ];then echo "core dump size set success" else echo -e "\33[31m core dump size set fail\33[0m" fi echo …

springBoot统一响应类型3.3版本

前言&#xff1a; 通过实践而发现真理&#xff0c;又通过实践而证实真理和发展真理。从感性认识而能动地发展到理性认识&#xff0c;又从理性认识而能动地指导革命实践&#xff0c;改造主观世界和客观世界。实践、认识、再实践、再认识&#xff0c;这种形式&#xff0c;循环往…

【空间变换】欧拉角与四元数

核心 欧拉角描述的是一种变换&#xff0c;只关注变换后的结果&#xff0c;不关注变换过程中的运动 而四元数不仅良好地表示了一种变换&#xff0c;也很好地表示了一种运动过程&#xff0c;又避免了万向节死锁Gimbal Lock变换顺序&#xff0c;是欧拉角变换的一部分&#xff0c;…

基于Linux下的MyBash命令解释器

项目介绍&#xff1a;⼀个⽤C语⾔实现的简单shell&#xff0c;可以接受⽤⼾输⼊的命令并执⾏操作&#xff0c;⽀持多管道和重 定向。 mybash---打造自己的命令解释器 目前我们Linux的系统默认的命令解释器是bash; 命令解释器&#xff08;也称为命令行解释器或shell&#xff0…

Linux常见使用场景

一、文件查看与内容操作 ​1. cat ​作用&#xff1a;查看文件内容&#xff08;一次性输出全部内容&#xff09;。​常用选项&#xff1a; -n&#xff1a;显示行号。-b&#xff1a;仅对非空行显示行号。 ​示例&#xff1a; cat file.txt # 查看文件内容 cat -n fil…

Ingredient-oriented Multi-Degradation Learning for Image Restoration论文阅读

摘要&#xff1a;重点在于关联多个任务本质的联系。 不同恢复任务的关联性很重要。 揭示退化现象的内在机理联系很有意义。 多合一的方法能在单一模型中处理多种退化问题&#xff0c;可扩展性较差。 成分导向范式挖掘不同图像退化现象背后的物理规律或特征模式。 成分导向退化重…

禅道后台命令执行漏洞

漏洞简介 禅道是第一款国产的开源项目管理软件。它集产品管理、项目管理、质量管理、文档管理、 组织管理和事务管理于一体&#xff0c;是一款专业的研发项目管理软件&#xff0c;完整地覆盖了项目管理的核心流程。 禅道管理思想注重实效&#xff0c;功能完备丰富&#xff0c;…

密码学——知识问答

目录 1、阐述公开密钥算法的定义&#xff0c;结合RSA算法说明公钥密码的基本要求。 说明公钥与私钥两种密码学并举例与其应用 1. 公钥密码学&#xff08;非对称加密&#xff09;&#xff1a; 2. 私钥密码学&#xff08;对称加密&#xff09;&#xff1a; 对比公钥与私钥密码…

PDF多表格结构识别与跨表语义对齐:基于对抗迁移的鲁棒相似度度量模型

文章目录 一. 项目结构二.流程分析2.1 批处理器核心代码解析 三. 跨页表格相似度匹配原理3.1 表头内容相似度-特征向量归一化3.2 表头内容相似度-余弦相似度3.3 定时缓存清理 ocr扫描有其局限性。对于pdf文本类型这种pdfbox&#xff0c;aspose-pdf&#xff0c;spire直接提取文本…

es 3期 第27节-运用Script脚本实现复杂需求

#### 1.Elasticsearch是数据库&#xff0c;不是普通的Java应用程序&#xff0c;传统数据库需要的硬件资源同样需要&#xff0c;提升性能最有效的就是升级硬件。 #### 2.Elasticsearch是文档型数据库&#xff0c;不是关系型数据库&#xff0c;不具备严格的ACID事务特性&#xff…

23、web前端开发之html5(四)

十二. HTML5实践示例 前面我们详细讲解了HTML5的特点&#xff0c;包括语义化标签、增强的表单功能、多媒体元素&#xff08;如<video>和<audio>&#xff09;、Canvas绘图、SVG集成以及离线存储等。以下是一些详细的HTML5实践示例&#xff0c;展示如何使用HTML5的新…