列表遍历删除元素时报java.util.ConcurrentModificationException的原因及解决方案

简介: 列表遍历删除元素时报java.util.ConcurrentModificationException的原因及解决方案

一、问题出现


测试代码


@Test
public void listTest(){
    List<String> list =new ArrayList<>();
    list.add("a");
    list.add("b");
    list.add("c");
    removeList0(list);
    list.forEach(System.out::println);
}
//直接遍历删除
public void removeList0(List<String> list){
    for (String s :
            list) {
        if (s.equalsIgnoreCase("c")) {
            list.remove(s);
        }
    }
}

测试结果


java.util.ConcurrentModificationException
  at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
  at java.util.ArrayList$Itr.next(ArrayList.java:859)
  at cn.hangtian.com.PackTest.removeList0(PackTest.java:499)
  at cn.hangtian.com.PackTest.listTest(PackTest.java:473)

二、问题原因


列表的foreach遍历方法中使用的迭代器中的遍历方法,迭代器还有一个修改列表计数器(modCount);而使用列表的remove()方法修改的是列表的修改列表计数器,二者值不等导致异常。


三、问题解决


单线程中使用迭代器的remove()方法或者利用索引删除。


1、迭代器删除


测试代码

@Test
public void listTest(){
    List<String> list =new ArrayList<>();
    list.add("a");
    list.add("b");
    list.add("c");
    removeList(list);
    list.forEach(System.out::println);
}
//通过迭代器删除
public void removeList(List<String> list){
    Iterator<String> iterator = list.iterator();
    while (iterator.hasNext()){
        String s = iterator.next();
        if (s.equalsIgnoreCase("c")){
            iterator.remove();
        }
    }
}

测试结果

a
b

2、索引方式删除


测试代码


@Test
public void listTest(){
    List<String> list =new ArrayList<>();
    list.add("a");
    list.add("b");
    list.add("c");
    removeList(list);
    list.forEach(System.out::println);
}
//通过索引删除
public void removeList0(List<String> list){
    for (int i = 0; i < list.size(); i++) {
        if (list.get(i).equalsIgnoreCase("c")) {
            list.remove(i);
        }
    }
}

测试结果

a
b

PS:多线程中请自行尝试搜索解决。😃


相关文章
|
3月前
|
关系型数据库 MySQL Java
【IDEA】java后台操作mysql数据库驱动常见错误解决方案
【IDEA】java后台操作mysql数据库驱动常见错误解决方案
118 0
|
8天前
|
JSON 前端开发 Java
【Bug合集】——Java大小写引起传参失败,获取值为null的解决方案
类中成员变量命名问题引起传送json字符串,但是变量为null的情况做出解释,@Data注解(Spring自动生成的get和set方法)和@JsonProperty
|
2月前
|
设计模式 Java 开发者
Java多线程编程的陷阱与解决方案####
本文深入探讨了Java多线程编程中常见的问题及其解决策略。通过分析竞态条件、死锁、活锁等典型场景,并结合代码示例和实用技巧,帮助开发者有效避免这些陷阱,提升并发程序的稳定性和性能。 ####
|
2月前
|
安全 Java 开发者
Java多线程编程中的常见问题与解决方案
本文深入探讨了Java多线程编程中常见的问题,包括线程安全问题、死锁、竞态条件等,并提供了相应的解决策略。文章首先介绍了多线程的基础知识,随后详细分析了每个问题的产生原因和典型场景,最后提出了实用的解决方案,旨在帮助开发者提高多线程程序的稳定性和性能。
|
2月前
|
人工智能 监控 数据可视化
Java智慧工地信息管理平台源码 智慧工地信息化解决方案SaaS源码 支持二次开发
智慧工地系统是依托物联网、互联网、AI、可视化建立的大数据管理平台,是一种全新的管理模式,能够实现劳务管理、安全施工、绿色施工的智能化和互联网化。围绕施工现场管理的人、机、料、法、环五大维度,以及施工过程管理的进度、质量、安全三大体系为基础应用,实现全面高效的工程管理需求,满足工地多角色、多视角的有效监管,实现工程建设管理的降本增效,为监管平台提供数据支撑。
49 3
|
2月前
|
存储 Java 开发者
在 Java 中,如何遍历一个 Set 集合?
【10月更文挑战第30天】开发者可以根据具体的需求和代码风格选择合适的遍历方式。增强for循环简洁直观,适用于大多数简单的遍历场景;迭代器则更加灵活,可在遍历过程中进行更多复杂的操作;而Lambda表达式和`forEach`方法则提供了一种更简洁的函数式编程风格的遍历方式。
|
2月前
|
Java API Apache
|
3月前
|
Java 程序员 编译器
Java|如何正确地在遍历 List 时删除元素
从源码分析如何正确地在遍历 List 时删除元素。为什么有的写法会导致异常,而另一些不会。
56 3
|
3月前
|
前端开发 小程序 Java
java基础:map遍历使用;java使用 Patten 和Matches 进行正则匹配;后端传到前端展示图片三种情况,并保存到手机
这篇文章介绍了Java中Map的遍历方法、使用Pattern和matches进行正则表达式匹配,以及后端向前端传输图片并保存到手机的三种情况。
31 1
|
3月前
|
Java
短频快task的java解决方案
本文探讨了Java自带WorkStealingPool的缺陷,特别是在任务中断方面的不足。普通线程池在处理短频快任务时存在锁竞争问题,导致性能损耗。文章提出了一种基于任务窃取机制的优化方案,通过设计合理的窃取逻辑和减少性能损耗,实现了任务的高效执行和资源的充分利用。最后总结了不同场景下应选择的线程池类型。