java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(Unknown Source) at java.util.ArrayList$Itr.next(Unknown Source) at ArrayListRemove.remove(ArrayListRemove.java:22) at ArrayListRemove.main(ArrayListRemove.java:14)
我们暂时先不管它,换成普通的遍历的写法:
写法二:
1 2 3 4 5 6 7 8
publicstaticvoidremove(ArrayList<String> list){ for (int i = 0; i < list.size(); i++) { String s = list.get(i); if (s.equals("bb")) { list.remove(s); } } }
这样子写运行时不报错了,但是执行完之后数组打印结果如下:
1 2 3 4 5
element : a element : bb element : ccc element : ccc element : ccc
可以发现并没有把所有的 “bb” 删除掉。
源码解析
我们看看这两种写法是怎样出错的。
首先看看方法二为什么运行结果出错,通过查看 ArrayList 的 remove 方法一探究竟。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
publicbooleanremove(Object o){ if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); returntrue; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { // 删除第一个匹配的元素 fastRemove(index); returntrue; } }
returnfalse; }
可以看到删除元素时只删除了第一个匹配到的元素。再查看具体的 fastRemove() 方法:
1 2 3 4 5 6 7 8
privatevoidfastRemove(int index){ modCount++; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // Let gc do its work }
public Iterator<E> iterator(){ returnnew Itr(); } /** * An optimized version of AbstractList.Itr */ privateclassItrimplementsIterator<E> { // The "limit" of this iterator. This is the size of the list at the time the // iterator was created. Adding & removing elements will invalidate the iteration // anyway (and cause next() to throw) so saving this value will guarantee that the // value of hasNext() remains stable and won't flap between true and false when elements // are added and removed from the list. protectedint limit = ArrayList.this.size; int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount;
publicbooleanhasNext(){ return cursor < limit; }
@SuppressWarnings("unchecked") public E next(){ if (modCount != expectedModCount) thrownew ConcurrentModificationException();
int i = cursor; if (i >= limit) thrownew NoSuchElementException();
Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) thrownew ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i]; }
publicvoidremove(){ if (lastRet < 0) thrownew IllegalStateException();
if (modCount != expectedModCount) thrownew ConcurrentModificationException();
publicstaticvoidremove(ArrayList<String> list){ // 这里要注意数组越界的问题,要用 >= 0 来界定 for (int i = list.size() - 1; i >= 0; i--) { String s = list.get(i); if (s.equals("bb")) { list.remove(s); } } }
写法四:
1 2 3 4 5 6 7 8 9
publicstaticvoidremove(ArrayList<String> list){ Iterator<String> it = list.iterator(); while (it.hasNext()) { String s = it.next(); if (s.equals("bb")) { it.remove(); } } }