JUnit中使用CustomComparator排序抛UnsupportedOperationException的修复
异常排查与修复方案
根因定位
从堆栈里的com.google.common.collect.UnmodifiableListIterator.set调用链可以直接定位问题:你代码中操作的Database.arrayList本质是Guava生成的不可变只读列表,并非可变的ArrayList实例。Collections.sort的实现原理是通过列表迭代器的set方法逐次调整元素位置完成排序,一旦遇到不支持元素修改的只读列表,就会直接抛出UnsupportedOperationException。哪怕变量名叫arrayList,只要实际引用的是不可变集合,就会触发这个异常。
可选修复方案
方案1:排序前拷贝为可变列表(兼容存量代码)
不要直接对原不可变列表执行排序操作,先把列表内容拷贝到真正可变的ArrayList实例上再执行排序逻辑:// 拷贝生成可修改的可变列表 List<MyObject> sortableData = new ArrayList<>(Database.arrayList); // 对可变副本执行排序 Collections.sort(sortableData, new CustomComparator()); // 如果需要回写排序结果到原存储对象,批量更新即可 Database.arrayList.clear(); Database.arrayList.addAll(sortableData);方案2:流式生成排序后的新列表(无侵入最安全)
基于Java 8+的Stream API直接生成排序后的新列表,全程不修改原列表内容,从根本上规避不可变集合的操作限制:List<MyObject> sortedData = Database.arrayList.stream() .sorted(new CustomComparator()) .collect(Collectors.toCollection(ArrayList::new));方案3:从源头修正列表初始化逻辑
排查Database.arrayList的赋值来源,避免把以下类型的不可变集合赋值给该变量:- Guava的
ImmutableList系列实现 - 经过
Collections.unmodifiableList()包装的只读列表 - Java 9+中
List.of()生成的不可变列表
直接用new ArrayList<>()初始化真正可变的列表,从根源上避免只读实例被传递到业务逻辑层。
- Guava的
额外健壮性提示
当前实现的CustomComparator存在空指针隐患:如果getStartDate()返回null,调用compareTo时会直接抛出空指针异常。可以在比较逻辑中补充空值判断,约定null值的排序优先级,提升代码稳定性。
内容的提问来源于stack exchange,提问作者Ady96
相关产品推荐
相关产品推荐

