java 不可变集合讲解

好的,我很乐意为您讲解 Java 不可变集合(Immutable Collections)

不可变集合是 Java 编程中一个非常重要的概念,它能帮助我们编写出更健壮、更安全、更易于理解和维护的代码。


🔒 什么是 Java 不可变集合?

不可变集合是指一旦创建,它的 内容、大小和结构就不能再被修改 的集合。

  • 创建后不可变: 您不能添加、删除或替换其中的任何元素。
  • 线程安全: 由于它们永远不会改变,所以它们天然就是 线程安全 的,无需额外的同步措施。
  • 元素引用不变: 集合存储的元素引用是不可变的,但如果元素本身是可变对象(例如一个自定义的类实例),那么该元素内部的状态仍然可以改变。

🛠️ 如何创建不可变集合?

从 Java 9 开始,JDK 提供了方便的静态工厂方法来创建不可变集合。

1. 使用 List.of(), Set.of(), Map.of() / Map.ofEntries() (Java 9+)

这是创建小型不可变集合的 首选和最简单 的方法。

  • 不可变列表 (Immutable List):

    java 复制代码
    List<String> immutableList = List.of("Apple", "Banana", "Cherry");
    // 尝试修改会抛出 UnsupportedOperationException
    // immutableList.add("Date"); 
  • 不可变集合 (Immutable Set):

    java 复制代码
    Set<Integer> immutableSet = Set.of(1, 2, 3);
  • 不可变映射 (Immutable Map):

    java 复制代码
    // 使用 key, value 成对传入
    Map<String, Integer> immutableMap = Map.of("A", 1, "B", 2);
    // 使用 Map.entry() 传入
    Map<String, Integer> immutableMapEntries = Map.ofEntries(
        Map.entry("X", 10),
        Map.entry("Y", 20)
    );

2. 使用 copyOf() 方法 (Java 10+)

如果您已经有一个可变的集合 ,并想基于它创建一个不可变的副本 ,可以使用 copyOf()

java 复制代码
List<String> mutableList = new ArrayList<>();
mutableList.add("One");
mutableList.add("Two");

// 创建一个不可变的新列表
List<String> immutableCopy = List.copyOf(mutableList); 

Set.copyOf()Map.copyOf() 也同样适用。

3. 使用 Collections.unmodifiable...() (传统方法)

在 Java 9 之前,通常使用 Collections 类提供的封装方法。它返回的是一个 视图(View),而不是一个新的不可变集合:

java 复制代码
List<String> mutableList = new ArrayList<>();
mutableList.add("Hello");

// 返回一个不可修改的视图
List<String> unmodifiableList = Collections.unmodifiableList(mutableList);

// 注意:如果 originalList 之后被修改了,unmodifiableList 也会反映这些修改!
// mutableList.add("World"); // 此时 unmodifiableList 也会多一个 "World"

⚠️ 核心区别: unmodifiableList视图 ,原始集合变它也变;而 List.of()List.copyOf() 创建的是 真正的、独立的不可变集合 。因此,推荐使用 Java 9+ 的 of()copyOf()


✨ 为什么使用不可变集合?

使用不可变集合有以下主要优势:

优势 描述
线程安全 无需担心多线程并发修改的问题,因为它们根本无法被修改,是天然的线程安全。
可预测性 数据的状态是固定的,更容易理解程序的执行流和调试错误。
用作常量 非常适合用作类的公共常量或配置数据,防止被外部代码意外修改。
更好的哈希 可以被安全地用作 Map 的键(如果它包含的元素也实现了正确的 equalshashCode),因为它们的状态永不改变。
设计模式 它们是函数式编程和面向对象设计中的一个重要组成部分(例如,用作 DTO/Value Object 的内部状态)。

❌ 不可变集合的限制

  • 无法修改: 这是最主要的限制。如果您需要一个经常需要添加、删除元素的集合,那么可变集合(如 ArrayList)是更好的选择。
  • 性能考量: 对于非常大的集合,每次修改都需要创建一个新的不可变集合副本(而不是修改现有集合),这可能会产生额外的内存开销和垃圾回收负担。

🚀 总结

特性 不可变集合(List.of() 可变集合(ArrayList
创建后 不能修改(大小、内容) 可以修改(添加、删除等)
线程安全 (天然) (需要外部同步)
使用场景 状态固定、配置、常量、线程间共享 频繁操作、临时数据存储
推荐方式 List.of(), Set.of(), Map.of(), copyOf() new ArrayList(), new HashMap()

在 Java 编程中,一个良好的实践是:尽可能使用不可变对象。只有在确实需要修改集合内容时,才使用可变集合。


您对不可变集合的某个具体方面,比如 不可变集合的内部实现原理 或者 与 Guava 不可变集合的区别 感兴趣吗?

相关推荐
翔云 OCR API2 小时前
NFC护照鉴伪查验流程解析-ICAO9303护照真伪查验接口技术方案
开发语言·人工智能·python·计算机视觉·ocr
2501_941111682 小时前
模板编译期哈希计算
开发语言·c++·算法
Qiuner2 小时前
Spring Boot 进阶:application.properties 与 application.yml 的全方位对比与最佳实践
java·spring boot·后端
寒山李白2 小时前
Mybatis使用教程之XML配置方式实现增删改查
xml·java·mybatis
Creeper.exe2 小时前
【C语言】分支与循环(上)
c语言·开发语言
Seven972 小时前
剑指offer-38、⼆叉树的深度
java
jllllyuz2 小时前
基于粒子群优化(PSO)的特征选择与支持向量机(SVM)分类
开发语言·算法·matlab
Kapaseker2 小时前
一文入门 Java Stream
java
optimistic_chen2 小时前
【Java EE进阶 --- SpringBoot】Spring事务
java·spring boot·笔记·spring·java-ee·事务