1 List<String> a = new ArrayList<String>();
4  for (String temp : a) {
5      if("1".equals(temp)){
6          a.remove(temp);
7 }
8 }

List<String> a = new ArrayList<String>();
for (String temp : a) {
if("2".equals(temp)){
a.remove(temp);
}
}

at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859) at java.util.ArrayList$Itr.next(ArrayList.java:831)
at luyudepackage.waitTest.main(waitTest.java:57)

 1 List a = new ArrayList();
4 Iterator i$= a.iterator(); 5 do 6 { 7 if(!i$.hasNext())
8         break;
9     String temp = (String)i\$.next();
10     if("1".equals(temp))
11         a.remove(temp);
12 } while(true);

1.foreach遍历集合，实际上内部使用的是iterator。

2.代码先判断是否hasNext，然后再去调用next，这两个函数是引起问题的关键。

3.这里的remove还是list的remove方法。

1 private void fastRemove(int index) {
2         modCount++;
3         int numMoved = size - index - 1;
4         if (numMoved > 0)
5             System.arraycopy(elementData, index+1, elementData, index,
6                              numMoved);
7         elementData[--size] = null; // clear to let GC do its work
8     }

1 public boolean add(E e) {
2         ensureCapacityInternal(size + 1);  // Increments modCount!!
3         elementData[size++] = e;
4         return true;
5     }

1 public Iterator<E> iterator() {
2         return new Itr();
3  }
 1 private class Itr implements Iterator<E> {
2         int cursor;       // index of next element to return
3         int lastRet = -1; // index of last element returned; -1 if no such
4         int expectedModCount = modCount;
5
6         public boolean hasNext() {
7             return cursor != size;
8         }
9
10         @SuppressWarnings("unchecked")
11         public E next() {
12             checkForComodification();//万恶之源
13             int i = cursor;
14             if (i >= size)
15                 throw new NoSuchElementException();
16             Object[] elementData = ArrayList.this.elementData;
17             if (i >= elementData.length)
18                 throw new ConcurrentModificationException();
19             cursor = i + 1;
20             return (E) elementData[lastRet = i];
21         }
22
23         public void remove() {
24             if (lastRet < 0)
25                 throw new IllegalStateException();
26             checkForComodification();
27
28             try {
29                 ArrayList.this.remove(lastRet);
30                 cursor = lastRet;
31                 lastRet = -1;
32                 expectedModCount = modCount;
33             } catch (IndexOutOfBoundsException ex) {
34                 throw new ConcurrentModificationException();
35             }
36         }
37
38         final void checkForComodification() {
39             if (modCount != expectedModCount)
40                 throw new ConcurrentModificationException();
41         }
42     }

1.在iterator初始化的时候（也就是for循环开始处），expectedModCount = modCount，猜测是和当时list内部的元素数量有关系(已证实)。

2.当cursor != size的时候，hasNext返回true

3.next()函数的第一行，checkForComodification()这个函数就是报错的原因 这个函数就是万恶之源

4.第39行，mod != expectedModCount 就会抛出ConcurrentModificationException()

接下来分析文章开头的第一个例子，为啥不会报错？

 1 public static void main(String[] args) throws Exception {
2         List<String> a = new ArrayList<String>();
5         for (String temp : a) {
6             System.out.println(temp);
7             if("2".equals(temp)){
9                 a.remove("2");
10             }
11         }
12 }

1

2

1 Iterator<String> it = a.iterator(); while(it.hasNext()){
2 String temp = it.next(); if(删除元素的条件){
3         it.remove();
4        }
5 }

 1  public void remove() {
2             if (lastRet < 0)
3                 throw new IllegalStateException();
4             checkForComodification();
5
6             try {
7                 ArrayList.this.remove(lastRet);
8                 cursor = lastRet;   //index of last element returned;-1 if no such
9                 lastRet = -1;
10                 expectedModCount = modCount;
11             } catch (IndexOutOfBoundsException ex) {
12                 throw new ConcurrentModificationException();
13             }
14         }

Ps再来看一个佐证

public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
for(int i : list){
System.out.println(i);
if(i == 2){
list.remove((Object)2);
}
}

}

1

2

posted @ 2017-07-11 08:16  丨核桃牛奶  阅读(20784)  评论(3编辑  收藏  举报