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

  • 相关阅读:
    VS2013诡异问题,虚方法、泛型,通通躺枪
    RabbitMQ与Redis队列对比
    CentOS 6.5中配置RabbitMQ
    RabbitMQ集群配置
    Ubuntu下的RabbitMQ安装与web管理配置
    EasyNetQ自定义异常消息处理
    2021年 B站1024程序节技术对抗赛
    01背包问题 之 动态规划(通俗解释)
    Jmeter Web 性能测试入门 (七):Performance 测试中踩过 Jmeter 的坑
    Jmeter Web 性能测试入门 (五):Jmeter 参数化 Request
  • 原文地址:https://www.cnblogs.com/zhiwenxi/p/11432065.html
Copyright © 2011-2022 走看看