说说ArrayList的ConcurrentModificationException

来源:互联网 发布:老大哥在看着你 知乎 编辑:程序博客网 时间:2024/06/06 12:57

试用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:

1Exception 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中

阅读全文
1 0
原创粉丝点击