Java中遍历集合的并发修改异常解决方案实例代码

 更新时间:2022年12月13日 15:35:53   作者:蓝桉cyq  
当你遍历集合的同时,又往集合中添加或者删除元素,就可能报并发修改异常,下面这篇文章主要给大家介绍了关于Java中遍历集合的并发修改异常解决方案的相关资料,需要的朋友可以参考下

遍历集合的删除元素的问题

问题引出:

当我们遍历集合从中找出某一批元素并删除的时候, 可能出现一种并发修改异常问题。

哪些变量会存在这个问题?

迭代器遍历集合且直接用集合删除元素的时候可能出现, 例如下面代码就会报错。

public static void main(String[] args) {
    Collection<String> list = new ArrayList<>();
    list.add("aaa");
    list.add("bbb");
    list.add("ccc");
    list.add("aaa");
    list.add("ddd");
    list.add("aaa");

    // 删除全部aaa元素
    Iterator<String> ite =  list.iterator();
    while (ite.hasNext()) {
        String item = ite.next();
        if ("aaa".equals(item)) {
            list.remove("aaa");
        }
    }
}

增强for循环遍历集合且直接用集合删除元素的时候可能出现, 例如下面代码同样会报错。

public static void main(String[] args) {
    Collection<String> list = new ArrayList<>();
    list.add("aaa");
    list.add("bbb");
    list.add("ccc");
    list.add("aaa");
    list.add("ddd");
    list.add("aaa");

    for (String item : list) {
        if ("aaa".equals(item)) {
            list.remove("aaa");
        }
    }
}

Lambda方法遍历同样会出现一样的bug

public static void main(String[] args) {
    Collection<String> list = new ArrayList<>();
    list.add("aaa");
    list.add("bbb");
    list.add("ccc");
    list.add("aaa");
    list.add("ddd");
    list.add("aaa");

    list.forEach(s -> {
        if ("aaa".equals(s)) {
            list.remove("aaa");
        }
    });
}

使用for循环, 不会报错, 但是删除数据会出现问题, 例如下面代码中会漏删aaa

public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<>();
    list.add("aaa");
    list.add("aaa");
    list.add("ccc");
    list.add("aaa");
    list.add("ddd");
    list.add("aaa");

    for (int i = 0; i < list.size(); i++) {
        String item = list.get(i);
        if ("aaa".equals(item)) {
            list.remove("aaa");
        }
    }

    System.out.println(list); // [ccc, ddd, aaa]
}

解决方案:

迭代器的解决方法: 迭代器遍历集合但是用迭代器自己的删除方法操作可以解决。

public static void main(String[] args) {
    Collection<String> list = new ArrayList<>();
    list.add("aaa");
    list.add("bbb");
    list.add("ccc");
    list.add("aaa");
    list.add("ddd");
    list.add("aaa");

    // 删除全部aaa元素
    Iterator<String> ite =  list.iterator();
    while (ite.hasNext()) {
        String item = ite.next();
        if ("aaa".equals(item)) {
            // shiy 迭代器删除方法, 删除当前所在元素
            ite.remove();
        }
    }

    System.out.println(list); // [bbb, ccc, ddd]
}

for循环的解决方法一: 从后往前删

public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<>();
    list.add("aaa");
    list.add("aaa");
    list.add("ccc");
    list.add("aaa");
    list.add("ddd");
    list.add("aaa");

    for (int i = list.size() - 1; i >= 0; i--) {
        String item = list.get(i);
        if ("aaa".equals(item)) {
            list.remove("aaa");
        }
    }

    System.out.println(list); // [ccc, ddd]
}

for循环的解决方法二: 删除完元素让 i 减1, i--

public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<>();
    list.add("aaa");
    list.add("aaa");
    list.add("ccc");
    list.add("aaa");
    list.add("ddd");
    list.add("aaa");

    for (int i = 0; i < list.size(); i++) {
        String item = list.get(i);
        if ("aaa".equals(item)) {
            list.remove("aaa");
            // 删除了元素i--
            i--;
        }
    }

    System.out.println(list); // [ccc, ddd]
}

总结

到此这篇关于Java中遍历集合的并发修改异常解决的文章就介绍到这了,更多相关Java遍历集合并发修改异常内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Effective Java (异常处理)

    Effective Java (异常处理)

    Effective Java (异常处理),需要的朋友可以参考一下
    2013-02-02
  • Java通过Callable实现多线程

    Java通过Callable实现多线程

    这篇文章主要介绍了Java通过Callable实现多线程,Callable的任务执行后可返回值,运行Callable任务可以拿到一个Future对象,Future表示异步计算的结果,它提供了检查计算是否完成的方法,以等待计算的完成,并检查计算的结果,需要的朋友可以参考下
    2023-10-10
  • Java Swing组件单选框JRadioButton用法示例

    Java Swing组件单选框JRadioButton用法示例

    这篇文章主要介绍了Java Swing组件单选框JRadioButton用法,结合具体实例形式分析了Swing单选框JRadioButton的使用方法及相关操作注意事项,需要的朋友可以参考下
    2017-11-11
  • SpringBoot Mybatis动态数据源切换方案实现过程

    SpringBoot Mybatis动态数据源切换方案实现过程

    这篇文章主要介绍了SpringBoot+Mybatis实现动态数据源切换方案过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • Maven中exec插件执行Java程序的实现

    Maven中exec插件执行Java程序的实现

    在Maven项目中,可以使用Maven的插件来执行Java程序,本文主要介绍了Maven中exec插件执行Java程序的实现,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12
  • 浅谈一下Java的双亲委派模式

    浅谈一下Java的双亲委派模式

    这篇文章主要介绍了一下Java的双亲委派模式,双亲委派指得是,JVM在加载类时,会委派给ExtClassLoader和BootstrapClassLoader进⾏加载,如果没加载到才由⾃⼰进⾏加载,需要的朋友可以参考下
    2023-04-04
  • springboot 整合hbase的示例代码

    springboot 整合hbase的示例代码

    这篇文章主要介绍了springboot 整合hbase的示例代码,本篇详细总结了hbase的Java客户端的使用,在实际开发过程中,还需要结合自身的情况做更加细致的整合与优化,需要的朋友可以参考下
    2022-04-04
  • JAVA集成本地部署的DeepSeek的图文教程

    JAVA集成本地部署的DeepSeek的图文教程

    本文主要介绍了JAVA集成本地部署的DeepSeek的图文教程,包含配置环境变量及下载DeepSeek-R1模型并启动,具有一定的参考价值,感兴趣的可以了解一下
    2025-03-03
  • Java web开发环境的搭建超完整步骤

    Java web开发环境的搭建超完整步骤

    这篇文章主要介绍了如何安装和配置IDEA 2020.1.1 X64版本软件,包括创建Java Web项目、配置Tomcat、部署Tomcat API以及创建和配置Servlet,通过这些步骤,新手可以快速搭建起Javaweb开发环境,需要的朋友可以参考下
    2024-11-11
  • 解决Eclipse发布到Tomcat丢失依赖jar包的问题

    解决Eclipse发布到Tomcat丢失依赖jar包的问题

    这篇文章介绍了如何在Eclipse中配置部署装配功能,以确保在将Web项目发布到Tomcat服务器时不会丢失任何依赖jar包,通过手动配置或使用构建工具脚本,可以自动化这个过程,提高开发效率和应用程序的稳定性,感兴趣的朋友跟随小编一起看看吧
    2025-01-01

最新评论