列表遍历删除元素时报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:多线程中请自行尝试搜索解决。😃


相关文章
|
5天前
|
存储 Java
Java学习笔记 List集合的定义、集合的遍历、迭代器的使用
Java学习笔记 List集合的定义、集合的遍历、迭代器的使用
|
6天前
|
存储 NoSQL Java
一天五道Java面试题----第十一天(分布式架构下,Session共享有什么方案--------->分布式事务解决方案)
这篇文章是关于Java面试中的分布式架构问题的笔记,包括分布式架构下的Session共享方案、RPC和RMI的理解、分布式ID生成方案、分布式锁解决方案以及分布式事务解决方案。
一天五道Java面试题----第十一天(分布式架构下,Session共享有什么方案--------->分布式事务解决方案)
|
2天前
|
Java 开发者
在Java编程中,if-else与switch作为核心的条件控制语句,各有千秋。if-else基于条件分支,适用于复杂逻辑;而switch则擅长处理枚举或固定选项列表,提供简洁高效的解决方案
在Java编程中,if-else与switch作为核心的条件控制语句,各有千秋。if-else基于条件分支,适用于复杂逻辑;而switch则擅长处理枚举或固定选项列表,提供简洁高效的解决方案。本文通过技术综述及示例代码,剖析两者在性能上的差异。if-else具有短路特性,但条件增多时JVM会优化提升性能;switch则利用跳转表机制,在处理大量固定选项时表现出色。通过实验对比可见,switch在重复case值处理上通常更快。尽管如此,选择时还需兼顾代码的可读性和维护性。理解这些细节有助于开发者编写出既高效又优雅的Java代码。
6 2
|
12天前
|
Java 容器
07 Java数组与数组操作(定义+遍历+排序+增删改查)(上)
07 Java数组与数组操作(定义+遍历+排序+增删改查)
28 8
|
7天前
|
监控 Java
Java文件夹复制解决方案:优化大文件与大量数据的处理
Java中复制文件夹及其内容,尤其是当处理大文件或文件夹(如几个GB)时,需要特别注意内存使用和性能优化。以下是一个详细的指导,包括如何避免内存溢出异常,并确保复制过程的高效性。
15 1
|
12天前
|
存储 Java API
07 Java数组与数组操作(定义+遍历+排序+增删改查)(下)
07 Java数组与数组操作(定义+遍历+排序+增删改查)
26 4
|
11天前
|
算法 安全 Java
探索Java中的并发编程:挑战与解决方案
【8月更文挑战第9天】 在Java世界中,并发编程是一个既令人兴奋又充满挑战的领域。它不仅为开发者提供了提高应用程序性能和响应性的机会,还带来了诸如数据一致性、线程安全和死锁等复杂问题。本文旨在通过分析Java并发的核心概念、常见并发模式及其实现方式,探讨如何在Java中有效地管理多线程环境,同时识别并解决并发编程过程中可能遇到的常见问题。
|
23天前
|
算法 Java
java使用递归及迭代方式实现前序遍历 中序遍历 后序遍历 以及实现层序遍历
java使用递归及迭代方式实现前序遍历 中序遍历 后序遍历 以及实现层序遍历
41 7
|
11天前
|
存储 算法 Java
LeetCode经典算法题:二叉树遍历(递归遍历+迭代遍历+层序遍历)以及线索二叉树java详解
LeetCode经典算法题:二叉树遍历(递归遍历+迭代遍历+层序遍历)以及线索二叉树java详解
31 0
|
1月前
|
存储 NoSQL 算法
实现分布式锁的Java解决方案
实现分布式锁的Java解决方案