ConcurrentModificationException併發修改異常

TaoChuan1997發表於2020-10-04

ConcurrentModificationException併發修改異常

#ConcurrentModificationException

在學習List集合的時候,在遍歷的時候修改元素,發現報了錯誤。

List<String> l=new ArrayList<String>();
        l.add("北京");
        l.add("南京");
        l.add("東京");

        Iterator<String> it=l.iterator();
        while(it.hasNext()){
            String ss=it.next();
            if(ss.equals("南京"))
            {
                l.add("上海");
            }
            System.out.println(ss);
        }

報錯
Exception in thread “main” java.util.ConcurrentModificationException
at java.util.ArrayList I t r . c h e c k F o r C o m o d i f i c a t i o n ( A r r a y L i s t . j a v a : 909 ) a t j a v a . u t i l . A r r a y L i s t Itr.checkForComodification(ArrayList.java:909) at java.util.ArrayList Itr.checkForComodification(ArrayList.java:909)atjava.util.ArrayListItr.next(ArrayList.java:859)
at com.neu.test4.ListDemo.main(ListDemo.java:32)
原因就出在32行上的next方法出了問題,集合的迭代器是不允許在遍歷的時候對集合集合進行操作的。
我們來看看API是怎麼說的
在這裡插入圖片描述
看原始碼:因為我們的集合l是ArrayList的物件,且使用了裡面的add()方法和Iterator方法。

public boolean add(E e) {
            modCount++;//5、而我們在操作時,實際修改次數會變化,但是預期修改次數不會變化。這就讓我們在checkForComodification方法裡比較兩個值的時候不同,就會丟擲併發修改異常。
            //而我們的modCount這個值來自於ArrayList,但是我們檢視ArrayList卻沒有,那是因為ArrayList繼承了AbstractList這個抽下類,而抽象類裡面就有這個值。如下
            add(e, elementData, size);
            return true;
    }
protected transient int modCount = 0;//6、AbstractList裡面的。一開始值為0,然後在呼叫next,會判斷,可是我們在next方法裡做了用了add方法,而add方法會修改modCount的值。造成異常。
public Iterator<E> iterator() {
        return new Itr();
    }

Iterator有返回了一個Itr物件。(在報錯裡面也可以看到)看next方法。

private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;//4、而在Itr類裡面,已經將實際修改次數賦值給了期望修改次數。

        @SuppressWarnings("unchecked")
        public E next() {//1、在進入next方法時,會呼叫checkForComodification方法。如下
            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];
        }
 final void checkForComodification() {
            if (modCount != expectedModCount)//2、而這個方法首先會比較兩個值:modCount(實際修改集合的次數)和expectedModCount(預期修改集合的次數)。
                throw new ConcurrentModificationException();//3、判斷,如果這兩個值不相等,就會丟擲我們所看到的ConcurrentModificationException異常。
        }

解決辦法

可以用for迴圈遍歷集合呀。哈哈哈哈,這樣就不會報錯了。

相關文章