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遍历集合并发修改异常内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java压缩集合的三种方法

    Java压缩集合的三种方法

    这篇文章主要介绍了Java压缩集合的三种方法,帮助大家更好的理解和使用Java,感兴趣的朋友可以了解下
    2021-01-01
  • java list中包含某个字符串的两种方法实现

    java list中包含某个字符串的两种方法实现

    在Java开发中,经常需要判断一个List中是否包含特定的字符串,包括使用contains()方法和循环遍历判断,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03
  • SpringMVC全局异常处理小结

    SpringMVC全局异常处理小结

    在开发中,不管是dao层、service层还是controller层,都有可能抛出异常,在springmvc中,能将所有类型的异常处理从各处理过程解耦出来,既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护,本文介绍SpringMVC全局异常处理,感兴趣的朋友一起看看吧
    2024-03-03
  • java开发环境的完整搭建过程

    java开发环境的完整搭建过程

    这篇文章主要给大家介绍了关于java开发环境的完整搭建过程,文中介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • java二路归并排序示例分享

    java二路归并排序示例分享

    这篇文章主要介绍了java二路归并排序示例,需要的朋友可以参考下
    2014-02-02
  • Java如何生成带网站链接(URL)的二维码

    Java如何生成带网站链接(URL)的二维码

    自从微信扫描出世,二维码扫描逐渐已经成为一种主流的信息传递和交换方式,这篇文章主要给大家介绍了关于Java如何生成带网站链接(URL)的二维码的相关资料,文中通过图文实例代码介绍的非常详细,需要的朋友可以参考下
    2021-07-07
  • JAVA 自定义线程池的最大线程数设置方法

    JAVA 自定义线程池的最大线程数设置方法

    这篇文章主要介绍了JAVA 自定义线程池的最大线程数设置方法,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下
    2020-06-06
  • 使用Java实现先查询缓存再查询数据库

    使用Java实现先查询缓存再查询数据库

    这篇文章主要介绍了使用Java实现先查询缓存再查询数据库,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-07-07
  • Java8通过CompletableFuture实现异步回调

    Java8通过CompletableFuture实现异步回调

    这篇文章主要介绍了Java8通过CompletableFuture实现异步回调,CompletableFuture是Java 8 中新增的一个类,它是对Future接口的扩展,下文关于其更多相关详细介绍需要的小伙伴可以参考一下
    2022-04-04
  • Java消息队列Kafka的简单概述

    Java消息队列Kafka的简单概述

    这篇文章主要介绍了Java消息队列Kafka的简单概述,消息系统负责将数据从一个应用程序传输到另一个应用程序,应用程序可以专注于数据,不担心如何共享它,需要的朋友可以参考下
    2023-07-07

最新评论