zoukankan      html  css  js  c++  java
  • 3种方式解决iterator迭代器ConcurrentModificationException

    3种方式解决iterator迭代器并发修改异常ConcurrentModificationException

    在使用迭代器的时候,时长会遇到 ConcurrentModificationException(并发修改异常)

    这也是很多人头疼的问题

    并发修改异常产生的原因

    在使用迭代器迭代集合的同时,使用原集合修改元素;如果迭代器发现自己和集合不一样,就会抛出 ConcurrentModificationException 异常。

    先拿出我写的小案例:

       Collection<String> list = new ArrayList<>();
        list.add("JAVA");
        list.add("Python");
        list.add("PHP");
        Iterator<String> it = list.iterator();
        while(it.hasNext()) {
            if (it.next().equals("PHP")) {
                list.add("我全都要");
            }
        }
    

    一运行,就抛异常

    Exception in thread "main" java.util.ConcurrentModificationException
    	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
    	at java.util.ArrayList$Itr.next(ArrayList.java:859)
    	at Test.main(Test.java:13)
    

    看看源码:

    at java.util.ArrayList$Itr.next(ArrayList.java:859)

        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }
    

    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    

    modCount 为 ArrayList 的类成员变量,用来记录其变化次数;而 expectedModCount 作为迭代器成员变量,则存储了 iterator 初始化时记录到的 ArrayList 中的 modCount 值。如果 modConut 和 expectedModCount 不相等,则抛出 ConcurrentModificationException 异常。

    解决方法

    这里我使用3种解决方案

    1. 使用列表迭代器
    2. 不使用迭代器遍历,使用普通for遍历
    3. 使用toArray

    第一种:使用列表迭代器

        List<String> list = new ArrayList<>();
        list.add("JAVA");
        list.add("Python");
        list.add("PHP");
        ListIterator<String> it = list.listIterator();
    
        while(it.hasNext()){
            if (it.next().equals("PHP")) {
                // list.add("以上几个");  //这里注意:直接修改原集合会抛出并发修改异常
                it.add("我全都要");
            }
        }
    	System.out.println(list);
    

    输出结果

    [JAVA, Python, PHP, 我全都要]
    

    第二种:不使用迭代器遍历,使用普通for遍历

        ArrayList<String> list = new ArrayList<>();
        list.add("JAVA");
        list.add("Python");
        list.add("PHP");
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).equals("PHP")) {
                list.remove("我全都要");
                list.add("C++");
            }
        }
        System.out.println(list);
    

    输出结果

    [JAVA, Python, PHP, C++]
    

    第三种:使用toArray

        ArrayList<String> list = new ArrayList<>();
        list.add("JAVA");
        list.add("Python");
        list.add("PHP");
        Object[] obj = list.toArray();
        for (int i = 0; i < obj.length; i++) {
            if (obj[i].equals("PHP")) {
                list.add(0,"今晚学习");
            }
        }
        System.out.println(list);
    

    输出结果

    [今晚学习, JAVA, Python, PHP]
    

    通过以上3种方法都可以解决 iterator 导致的并发修改异常。

    如果非要使用迭代器修改集合,可以使用列表迭代器 ListIterator

  • 相关阅读:
    DedeCMS系统301重定向配置方法详解
    dedecms批量更新静态时提示:没有该栏目数据 可能缓存的解决方法
    修改织梦dedecms后台默认admin账号的方法
    织梦DeDeCMS动态热点文章排行调用方法
    文件与字符串处理时常见的问题(中文英文)
    基于OpenCV全景拼接(Python)SIFT/SURF
    解决关闭ssh后网页停止服务的方法,利用nohup
    解决宝塔面板没有命令行问题 && 查看宝塔面板项目环境
    python 正则表达式
    JAVAC 不是内部或外部命令
  • 原文地址:https://www.cnblogs.com/zhiwenxi/p/11432065.html
Copyright © 2011-2022 走看看