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

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

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

蓝桉cyq   2022-12-13 我要评论

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

问题引出:

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

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

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

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]
}

总结

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们