ConcurrentModificationException并发修改异常

ConcurrentModificationException并发修改异常

原因分析

可以通过遍历索引也可以通过迭代器进行遍历。在我们使用迭代器进行遍历集合的时候,会获取到当前集合的迭代对象。在里面有封装了迭代器的remove方法与集合自带的remove方法,如果我们调用迭代器对象的remove方法是没问题的,但是当我们调用集合自带的remove方法时,就会产生ConcurrentModificationException 并发修改异常。也就是说,当我们通过非迭代器进行遍历集合的时候,是不允许集合本身在结构上发生变化的。

增删操作会导致 预期数量和 计数器的数量不一致,就会导致并发修改异常

解决方式

1,ListIterator列表迭代器(list特有的迭代器),将添加、删除元素交给迭代器去做,而非集合

java 复制代码
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("B");
list.add("C");

ListIterator<String> stringListIterator = list.listIterator();
while (stringListIterator.hasNext()) {
    String element = stringListIterator.next();
    if(StringUtils.equals(element,"C")) {
        // 在遍历时向列表中添加元素
        stringListIterator.add("D");
    }
}
System.out.println(list);//[A, B, B, C, D]

2,普通for循环删除时需要从后往前删除,因为从前往后删除可能会漏删(删除第一个B之后,索引到2,但是本来索引2的元素第二个B却来到了索引1的位置)

java 复制代码
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("B");
list.add("C");

for (int i = list.size()-1; i >= 0; i--) {
    if(StringUtils.equals(list.get(i),"B")) {
        list.remove("B");
    }
}

System.out.println(list);

3,使用CopyOnWriteArrayList集合,底层解决并发修改异常,就可以使用集合的增删方法在遍历时操作

java 复制代码
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("B");
list.add("C");

CopyOnWriteArrayList<String> copyOnWriteArrayList = new CopyOnWriteArrayList(list);
for (String ele :copyOnWriteArrayList){
    if(StringUtils.equals(ele,"C")) {
        // 在遍历时向列表中添加元素
        copyOnWriteArrayList.add("D");
    }
}

System.out.println(copyOnWriteArrayList);//[A, B, B, C, D]

4,当遍历时需要删除元素时,可以使用普通迭代器,普通迭代器没有新增方法

java 复制代码
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("B");
list.add("C");
//普通迭代器,只能删除,没有add
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
    String next = iterator.next();
    if(StringUtils.equals(next,"B")) {
        iterator.remove();//迭代器删除第一个B,然后hasNext拉到下一个B,迭代器再删除一次
    }
}
System.out.println(list);//[A, C]

5,增强for循环底层采用迭代器,遍历时删除(新增)只能用集合的删除(新增)方法,还会报并发修改异常

java 复制代码
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("B");
list.add("C");

for (String element : list) {//Caused by: java.util.ConcurrentModificationException: null
    if(StringUtils.equals(element,"B")) {
        list.add("B");
    }
}
System.out.println(list);//[A, B, B, C, D]
相关推荐
别动我齐刘海3 小时前
C++ 工程化学习
java·linux·前端·c++·学习·机器学习·机器人
code2cat4 小时前
Java进阶篇之AtomicLongFieldUpdater:把累计额度留在对象字段中
java·cas·并发编程
WeiXin_DZbishe4 小时前
基于springboot城市公交实时运营与调度系统-计算机毕设 附源码【课程设计】66173
java·vue.js·spring boot·后端·python·php·课程设计
泡茶喝茶写代码4 小时前
A股量化数据工程:从 REST 接口到策略信号(第 18 篇):放量缩量异动扫描
java·python·股票数据api·股票数据api接口·股票api数据接口·股票量化数据api·股票量化数据接口
wewowilling5 小时前
认识微服务
java·运维·微服务·springcloud
代码什么用5 小时前
Java Web 7-10
java·servlet
蜗牛互联网7 小时前
GPT-6 与 Intelligent UI:从回答到可审计操作的产品迁移
java·人工智能·后端
SL_staff7 小时前
运维救火实录:钉钉考勤API变更引发工资计算异常,我们用JVS-Logic可视化逻辑引擎实现分钟级热修复
java·mysql·全栈
SunnyDays10117 小时前
Java 查找并高亮 Word 文字:精确查找及正则表达式模糊查找
java·查找文字·word 文档·高亮文字·正则匹配查找·模糊查找