欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 旅游 > java数组ArrayList迭代修改的ConcurrentModificationException错误

java数组ArrayList迭代修改的ConcurrentModificationException错误

2024/10/24 17:27:21 来源:https://blog.csdn.net/GDUT_xin/article/details/139604346  浏览:    关键词:java数组ArrayList迭代修改的ConcurrentModificationException错误

报错:

Exception in thread "main" java.util.ConcurrentModificationExceptionat java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)at java.util.ArrayList$Itr.next(ArrayList.java:859)at net.micah.Test.main(Test.java:20)

我写的demo:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;public class Test {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("a");list.add("b");list.add("c");list.add("d");list.add("e");list.add("f");// 隐式创建迭代器 Itr(报错:ConcurrentModificationException) for (String next : list) {System.out.println(next);if (Objects.equals(next, "d")) {list.remove(next);}}System.out.println(list);// fori (无法实时拿到数组index更新,导致index对不上,导致错误的修改)for (int i = 0 ; i < list.size(); i++) {String next = list.get(i);System.out.println(next);if(Objects.equals(next, "d") || Objects.equals(next, "e")) {list.remove(next);}}System.out.println(list);// 显式迭代器(安全可靠)Iterator<String> iterator = list.iterator();while (iterator.hasNext()) {String next = iterator.next();System.out.println(next);if (Objects.equals(next, "d")) {iterator.remove();}}System.out.println(list);}}

迭代器内部是闭环的,校验逻辑为:

        final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException();}

expectedModCount 是在创建 Itr(迭代器内部类) 的时候赋值,为那个瞬间的 modCount

private class Itr implements Iterator<E> {int cursor;       // index of next element to returnint lastRet = -1; // index of last element returned; -1 if no suchint expectedModCount = modCount;Itr() {}

① 从源代码上说,这个 expectedModCount 只在迭代器的内部方法调用时被修改,而且 modCount + 1 时 expectedModCount 会和 modCount 保持同步。
也就是说,一旦创建了迭代器(包含 foreach 的情况),就只能调用 Itr 给的方法进行 “modify”,不然下次 checkForComodification 检查必定过不了。(modCount + 1 了,但是 expectedModCount 没有变,导致不相等)

② 从设计原则上说,迭代器一旦生成,就对应生成了游标(cursor),对父类变量(ArrayList.this.elementData)进行遍历操作,你要对父类变量进行变更,特别是触动了数据下标的变化,一定要让我来操作,不然我不知道,迭代的后续操作就不正确(安全)了。这就是“对修改封闭”(开闭原则的闭)。

解决方案:

  1. 用显式迭代器的内部方法进行集合的修改
  2. 处理成新集合,对新集合进行后续操作
  3. fori的反向操作(反向可以减少remove对index变化的影响,但是add操作还是会被影响)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com