ArrayList测试遭遇java.util.ConcurrentModificationException问题求助
解决ArrayList的ConcurrentModificationException问题
嘿,这个问题我之前也踩过坑!看起来你以为是在迭代前修改集合,但实际还是触发了并发修改异常,大概率是迭代器的创建时机比你想象的早,或者你用了隐式的迭代器(比如forEach循环)却没注意到。
常见原因分析
- 迭代器已创建后修改集合:ArrayList的迭代器是快速失败(fail-fast)的,一旦迭代器被创建,之后如果集合被修改(除了迭代器自己的
remove()/add()方法),迭代时就会抛出ConcurrentModificationException。你可能以为修改是在迭代前,但实际代码里迭代器已经提前初始化了,比如:List<String> list = new ArrayList<>(); Iterator<String> iter = list.iterator(); // 这里已经创建了迭代器 list.add("test"); // 迭代器创建后修改集合 iter.next(); // 这里就会抛出异常,对应你的第23行 - 隐式迭代器的坑:Java的
for-each循环底层就是用迭代器实现的,如果你在for-each循环之前的某个地方,看似是“迭代前”但其实已经触发了迭代器的创建(比如某些方法内部偷偷用了迭代器,不过更常见的是你把修改操作放在了迭代器创建之后)。
解决方案
根据你的场景,有几个靠谱的解决办法:
- 确保修改完全在迭代器创建之前
把所有集合修改操作放在迭代器初始化(或者for-each循环开始)之前,比如:List<Integer> nums = new ArrayList<>(Arrays.asList(1,2,3)); nums.add(4); // 先完成所有修改 // 再开始迭代 for (Integer num : nums) { System.out.println(num); } - 用迭代器自带的修改方法
如果需要在迭代过程中修改集合,一定要用迭代器提供的remove()(或者ListIterator的add()/set())方法,这些方法会同步迭代器和集合的状态:List<Integer> nums = new ArrayList<>(Arrays.asList(1,2,3)); ListIterator<Integer> iter = nums.listIterator(); while (iter.hasNext()) { int num = iter.next(); if (num == 2) { iter.remove(); // 安全修改,不会触发异常 } } - 改用CopyOnWriteArrayList
如果你的场景确实需要在迭代时修改集合(比如多线程环境,或者逻辑上无法避免),可以用java.util.concurrent.CopyOnWriteArrayList,它通过复制底层数组来避免并发修改异常,不过适合读多写少的场景:List<String> list = new CopyOnWriteArrayList<>(); list.add("a"); // 迭代时修改也不会抛异常 for (String s : list) { list.add("b"); }
排查小技巧
你可以仔细检查第23行的上下文:
- 看看迭代器(包括
for-each循环)是不是在修改集合之前就已经被创建了? - 有没有在其他地方(比如之前的方法调用)偷偷创建了迭代器?
内容的提问来源于stack exchange,提问作者Votic98
相关产品推荐
相关产品推荐

