ArrayList迭代器抛出ConcurrentModificationException问题咨询
嘿,我来帮你搞清楚这个让人头疼的异常!你以为只有多线程并发修改集合才会触发ConcurrentModificationException?其实不然——单线程环境下,当你用迭代器遍历集合的同时,直接修改了集合本身(比如调用add()、remove()、clear()这类方法),迭代器的fail-fast机制也会抛出这个异常。
为什么第7行itr.next()会报错?
迭代器在创建时会记录集合的修改次数(modCount),之后每次调用next()都会检查当前集合的修改次数和迭代器记录的是否一致。如果不一致(比如你在遍历过程中直接修改了集合),就会抛出这个异常,以此来避免迭代器拿到过期的数据。
你提到代码里有if (userList.size() == 0)的逻辑,大概率是在这个if分支里,你对正在迭代的userPrograms集合执行了修改操作(比如添加新元素、删除元素),这就导致迭代器的修改计数和集合实际的修改计数不匹配,等到下一次调用itr.next()时就触发了异常。
解决方案
根据你的修改场景,有几种常用的解决方式:
1. 如果是删除元素:使用迭代器自带的remove()方法
不要直接调用集合的remove(),而是用迭代器提供的remove()方法,它会同步更新迭代器的修改计数,避免异常:
Iterator<userPrograms> itr = userPrograms.iterator(); while (itr.hasNext()) { userPrograms current = itr.next(); // 第7行不再报错 if (userList.size() == 0) { // 满足条件时用迭代器的remove方法删除当前元素 itr.remove(); } }
2. 如果是添加/批量修改元素:先用临时集合存储修改内容,遍历完成后统一更新原集合
直接在遍历过程中添加元素会触发异常,你可以先把要添加的元素存到一个临时集合里,等遍历完原集合后再统一添加:
List<userPrograms> tempAddList = new ArrayList<>(); Iterator<userPrograms> itr = userPrograms.iterator(); while (itr.hasNext()) { userPrograms current = itr.next(); if (userList.size() == 0) { // 把要添加的元素先放到临时集合 tempAddList.add(new userPrograms(...)); } } // 遍历完成后,统一把临时集合的元素添加到原集合 userPrograms.addAll(tempAddList);
3. 使用并发安全集合(比如CopyOnWriteArrayList)
如果你的场景允许,可以替换集合类型为java.util.concurrent.CopyOnWriteArrayList,它的迭代器是基于集合的快照创建的,遍历过程中修改集合不会触发异常(但要注意,迭代器看不到遍历过程中对集合的修改,适合读多写少的场景):
List<userPrograms> userPrograms = new CopyOnWriteArrayList<>(); // 之后的遍历和修改逻辑可以保持不变 Iterator<userPrograms> itr = userPrograms.iterator(); while (itr.hasNext()) { userPrograms current = itr.next(); if (userList.size() == 0) { userPrograms.add(new userPrograms(...)); } }
内容的提问来源于stack exchange,提问作者user9213141

