說說ArrayList的ConcurrentModificationException

試用for-earch遍歷ArrayList,調用remove方法時候,常常回報ConcurrentModificationException異常,今天來從源碼上解析這個問題.

列出來問題

代碼1:

     ArrayList<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        list.add("2");
        list.add("2");
        for (String e : list) {
            System.out.println(e);
            if (e.equals("1")) {
                list.remove(e);
            }
        }

output:

1
Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
    at java.util.ArrayList$Itr.next(ArrayList.java:851)
    at com.own.learn.jdk.ref.Test.main(Test.java:17)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

``
**代碼2:**
    ArrayList<String> list = new ArrayList<>();
    list.add("1");
    list.add("2");
    list.add("2");
    list.add("2");
    for (int i=0; i< list.size(); i++) {
        String e =  list.get(i);
        System.out.println(e);
        if (e.equals("2")) {
            list.remove(e);
        }
    }
output:

1
2
2

**代碼三:**
    ArrayList<String> list = new ArrayList<>();
    list.add("1");
    list.add("2");
    list.add("2");
    list.add("2");
    for (Iterator<String> it = list.iterator(); it.hasNext();) {
        String next = it.next();
        if(next.equals("2"))
            it.remove();
        System.out.println(next);
    }
output:

1
2
2
2


###解決問題
1,checkForComodification報錯,查看源碼:
  final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
我們可以清楚看到,modCount和expectedModCount不相等的時候,纔有這個問題
list自帶的reomve方法調用了fastRemove是:
  private void fastRemove(int index) {
    modCount++;
    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work
}
modCount和expectedModCount方法不同步
而Itr中的remove方法:
  public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            ArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

“`
modCount和expectedModCount方法同步
到這裏ConcurrentModificationException解決了
2,代碼2中輸出少了一個數字,爲啥呢.答案在上面的fastRemove中

發佈了54 篇原創文章 · 獲贊 56 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章