1. 不可变集合的修改操作
1.1 Arrays.asList 返回的 List
List<String> list = Arrays.asList("a", "b");
list.add("c"); // UnsupportedOperationException
list.remove(0); // UnsupportedOperationException
list.clear(); // UnsupportedOperationException
Arrays.asList 返回的 List 不能增删元素,只能 set。
1.2 Collections.singletonList、Collections.emptyList
List<String> list = Collections.singletonList("a");
list.add("b"); // UnsupportedOperationException
list.remove("a"); // UnsupportedOperationException
list.clear(); // UnsupportedOperationException
这些方法返回的 List 是不可变的。
1.3 List.of (Java 9+)
List<String> list = List.of("a", "b");
list.add("c"); // UnsupportedOperationException
list.remove("a"); // UnsupportedOperationException
List.of 返回的也是不可变集合。
1.4 Map.of、Set.of
同理,Map.of、Set.of 也是不可变的。
2. 只读视图(Unmodifiable Views)
比如 Collections.unmodifiableList、Collections.unmodifiableMap:
List<String> source = new ArrayList<>();
List<String> list = Collections.unmodifiableList(source);
list.add("a"); // UnsupportedOperationException
list.remove("a"); // UnsupportedOperationException
list.clear(); // UnsupportedOperationException
这些方法返回的是原集合的只读视图,任何修改都会抛异常。
3. 部分集合操作被禁止
有些集合只实现了部分操作,比如:
java.util.AbstractList的默认实现,某些方法没有被子类覆盖时会抛出该异常。java.util.AbstractMap、AbstractSet也是类似。
4. 固定大小集合
如 Arrays.asList 返回的 List,底层是数组,不能改变大小。
5. 自定义集合类未实现某些方法
如果你自己继承了某个集合类,某些方法没有实现,直接调用父类的默认实现,也会抛出该异常。
6. JDK 某些特殊集合
Collections.nCopies返回的 List(固定元素数量,不可变)Collections.emptyList、emptySet、emptyMapCollections.singleton、singletonMap
7. 迭代器的 remove 操作
有些集合的 iterator 不支持 remove 操作:
List<String> list = List.of("a", "b");
Iterator<String> it = list.iterator();
it.next();
it.remove(); // UnsupportedOperationException
8. 多线程并发集合的某些操作
如 CopyOnWriteArrayList 的 iterator 不支持 remove。
总结
只要你对不可变集合、只读视图、固定大小集合或者未完全实现的集合类调用了修改方法(add、remove、clear、set、put、remove等),就会抛出 UnsupportedOperationException。
如何避免?
- 如果需要修改集合,请用如
new ArrayList<>(...)、new HashSet<>(...)等可变集合。 - 如果只读,则不要调用修改方法。
- 检查集合的创建方式,尽量避免对不可变集合进行修改操作。
9. Stream 相关操作
例如,使用 Java 8 Stream API 生成的集合有时也是不可变的:
List<String> list = Stream.of("a", "b").collect(Collectors.toList());
// 默认情况下 Collectors.toList() 返回的是 ArrayList,可变。
// 但如果用 Collectors.toUnmodifiableList() (Java 10+)
List<String> unmodList = Stream.of("a", "b").collect(Collectors.toUnmodifiableList());
unmodList.add("c"); // UnsupportedOperationException
10. 第三方库的不可变集合
很多第三方库(如 Guava、Apache Commons Collections)都提供了不可变集合,比如 Guava 的 ImmutableList:
List<String> guavaList = ImmutableList.of("a", "b");
guavaList.add("c"); // UnsupportedOperationException
guavaList.remove("a"); // UnsupportedOperationException
11. Arrays 工具类中的其它方法
除了 Arrays.asList,还有如 Arrays.setAll 返回的集合,也可能是不可变的。
12. 多层包装导致
有时候集合被多层包装,导致你误以为是可变的。例如:
List<String> list = Collections.unmodifiableList(Arrays.asList("a", "b"));
// 虽然底层是 Arrays.asList,但外层包装成了只读视图
list.set(0, "c"); // 仍然 UnsupportedOperationException
13. 子类未覆盖父类方法
比如你继承 AbstractList,只实现了 get 和 size,没实现 remove,那么调用 remove 会抛异常:
class MyList extends AbstractList<String> {
public String get(int index) { ... }
public int size() { ... }
// 没有实现 remove(int index)
}
MyList list = new MyList();
list.remove(0); // UnsupportedOperationException
14. JDK 内部特殊集合
有些 JDK API 返回的集合本身就是只读的,比如:
Collections.list(enumeration)返回的 ListSystem.getProperties().entrySet()返回的 SetMap.keySet()、Map.values()、Map.entrySet()的某些实现
这些集合的某些操作可能不被支持。
15. Map、Set 的只读视图
类似于 List,Map 和 Set 也有只读视图:
Map<String, String> map = Collections.unmodifiableMap(new HashMap<>());
map.put("a", "b"); // UnsupportedOperationException
16. 其他常见误区
- 有些集合支持部分操作,比如
remove支持,但add不支持,或者反之。 - 迭代器的
remove()方法不是所有集合都实现,有些会抛异常。
总结补充
UnsupportedOperationException 本质上是集合设计者用来保护集合不被非法修改的机制。
- 只读集合:不能修改
- 固定大小集合:不能增删,只能 set
- 未完全实现的集合:部分方法不能用
- 迭代器:不是所有都支持 remove
如何排查
- 定位集合的来源:看是怎么创建的,用了哪些工厂方法或包装器。
- 查阅文档:官方文档和第三方库文档都会说明哪些操作被支持。
- 调试类型:通过
getClass()打印集合的实际类型,判断底层实现。 - 避免误用:如果需要修改集合,始终用标准的可变集合,如
ArrayList、HashSet、HashMap。
521

被折叠的 条评论
为什么被折叠?



