在Java集合框架中,Collections类提供了一系列unmodifiableXXX静态方法,用于创建对应集合的不可变视图,让开发者可以快速得到不可被修改的集合实例,在需要保护集合数据不被篡改的场景下非常实用。

Collections.unmodifiableXXX系列方法概述
Collections工具类针对常见的集合类型都提供了对应的不可变视图创建方法,主要包括以下几类:
unmodifiableList(List<? extends T> list):创建不可变的List视图unmodifiableSet(Set<? extends T> set):创建不可变的Set视图unmodifiableMap(Map<? extends K, ? extends V> map):创建不可变的Map视图unmodifiableSortedSet(SortedSet<T> set):创建不可变的排序Set视图unmodifiableSortedMap(SortedMap<K, V> map):创建不可变的排序Map视图unmodifiableNavigableSet(NavigableSet<T> set):创建不可变的导航Set视图unmodifiableNavigableMap(NavigableMap<K, V> map):创建不可变的导航Map视图
基础使用示例
创建不可变List
首先创建可变的原始List,再通过Collections.unmodifiableList得到不可变视图,后续对不可变视图的修改操作会直接抛出异常。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class UnmodifiableListDemo {
public static void main(String[] args) {
// 创建原始可变List
List<String> originalList = new ArrayList<>();
originalList.add("Java");
originalList.add("Python");
originalList.add("Go");
// 创建不可变List视图
List<String> unmodifiableList = Collections.unmodifiableList(originalList);
// 读取操作正常执行
System.out.println("不可变List内容:" + unmodifiableList);
System.out.println("第一个元素:" + unmodifiableList.get(0));
// 尝试修改不可变List,会抛出UnsupportedOperationException
try {
unmodifiableList.add("C++");
} catch (UnsupportedOperationException e) {
System.out.println("添加元素失败:" + e.getMessage());
}
// 修改原始List,不可变视图的内容会同步变化
originalList.add("C++");
System.out.println("修改原始List后,不可变List内容:" + unmodifiableList);
}
}
创建不可变Map
Map的不可变视图创建方式和List类似,同样支持读取操作,不支持修改操作。
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class UnmodifiableMapDemo {
public static void main(String[] args) {
// 创建原始可变Map
Map<String, Integer> originalMap = new HashMap<>();
originalMap.put("Java", 1);
originalMap.put("Python", 2);
originalMap.put("Go", 3);
// 创建不可变Map视图
Map<String, Integer> unmodifiableMap = Collections.unmodifiableMap(originalMap);
// 读取操作正常执行
System.out.println("不可变Map内容:" + unmodifiableMap);
System.out.println("Java对应的值:" + unmodifiableMap.get("Java"));
// 尝试修改不可变Map,会抛出UnsupportedOperationException
try {
unmodifiableMap.put("C++", 4);
} catch (UnsupportedOperationException e) {
System.out.println("添加键值对失败:" + e.getMessage());
}
}
}
核心特性解析
不可变视图不等于不可变集合
需要特别注意,Collections.unmodifiableXXX创建的是原始集合的不可变视图,而不是完全独立的不可变集合。如果原始集合被修改,不可变视图的内容也会随之变化,这一点从上面的List示例中可以看到。如果需要完全独立的不可变集合,需要先复制原始集合的内容,再创建不可变视图。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class IndependentUnmodifiableDemo {
public static void main(String[] args) {
List<String> originalList = new ArrayList<>();
originalList.add("Java");
originalList.add("Python");
// 先复制原始集合内容,再创建不可变视图,得到完全独立的不可变集合
List<String> copyList = new ArrayList<>(originalList);
List<String> independentUnmodifiableList = Collections.unmodifiableList(copyList);
// 修改原始集合,不可变视图内容不会变化
originalList.add("Go");
System.out.println("原始List:" + originalList);
System.out.println("独立不可变List:" + independentUnmodifiableList);
}
}
修改操作会抛出的异常
对不可变视图执行任何修改操作,包括添加、删除、替换元素等,都会抛出UnsupportedOperationException,这是运行时异常,不需要强制捕获,但开发中需要避免此类操作。
支持所有集合的读取操作
不可变视图只是禁止了修改操作,所有的读取操作,比如size()、get()、contains()、iterator()等都可以正常执行,和原始集合的读取行为一致。
适用场景
- 当需要将集合作为参数传递给其他方法,且不希望方法内部修改集合内容时,可以传递不可变视图,避免外部集合被意外修改。
- 当集合的内容在初始化后不需要再变化,且需要对外暴露时,可以返回不可变视图,保护内部数据。
- 在多线程场景下,如果集合初始化后不再修改,使用不可变视图可以避免额外的同步开销,因为不可变对象本身就是线程安全的。
和其他不可变集合方式的对比
除了Collections.unmodifiableXXX,Java中还有其他创建不可变集合的方式,比如Java 9+的List.of()、Set.of()、Map.of()方法,以及Guava库的不可变集合工具类。它们的区别如下:
| 方式 | 是否独立不可变 | 是否允许null元素 | 适用Java版本 |
|---|---|---|---|
| Collections.unmodifiableXXX | 否(是视图) | 允许(取决于原始集合) | 所有Java版本 |
| List.of()/Set.of()/Map.of() | 是 | 不允许 | Java 9及以上 |
| Guava不可变集合 | 是 | 不允许 | 所有Java版本(需引入依赖) |
注意事项
- 不要对不可变视图执行修改操作,否则会抛出运行时异常,影响程序正常运行。
- 如果原始集合是可变的,且后续可能被修改,那么不可变视图的内容也会变化,需要根据需求判断是否需要复制原始集合内容。
- 不可变视图的迭代器也是不可变的,调用迭代器的
remove()方法同样会抛出UnsupportedOperationException。
使用Collections.unmodifiableXXX创建不可变集合时,要明确其视图特性,根据实际场景选择是否需要复制原始集合,避免因为原始集合的修改导致不可变视图的内容不符合预期。
JavaCollections.unmodifiableXXX不可变集合集合操作修改时间:2026-07-04 22:51:30