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 不可变集合的区别 感兴趣吗?

相关推荐
松仔log1 小时前
JetPack——Paging3+Room
android·java·zoom
biter down6 小时前
14:pytest-order 插件 顺序控制案例
开发语言·python·pytest
郝学胜-神的一滴6 小时前
Qt 高级开发 009: C++ Lambda 表达式
开发语言·c++·qt·软件构建
星栈独行6 小时前
我在 Rust 全栈项目里用 JWT 做无状态认证
开发语言·后端·rust·前端框架·开源·github·web
Lei活在当下6 小时前
先用起来,再理解,关于协程Coroutine应该知道的事
android·java·jvm
石山代码7 小时前
C++ 轻量级日志系统
开发语言·c++
Java爱好狂.7 小时前
Java程序员体系化学习路线(2026最新版)
java·后端·java面试·java架构师·java程序员·java八股文·java学习路线
tongluowan0077 小时前
以ReentrantLock为例解释AQS的工作流程
java·模板方法模式·aqs·reentrantlock
小技与小术7 小时前
玩转Flask
开发语言·python·flask
SilentSamsara7 小时前
Python 性能优化:tracemalloc、profiling 与 C 扩展加速
开发语言·python·青少年编程·性能优化