• 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

  • 相关阅读:
    Java IO总结
    Tomcat处理一个HTTP请求的过程
    Tomcat的web项目部署方式
    Tomcat性能调优
    jquery基础知识汇总
    Javascript中的正则表达式
    HTTP首部
    HTTPS
    Javascript中关于cookie的那些事儿
    HTTP请求方法详解
  • 原文地址:https://www.cnblogs.com/zhiwenxi/p/11432065.html
Copyright © 2020-2023  润新知