ArrayList的迭代器
在看阿里巴巴Java开发手册终极版v1.3.0.pdf发现了这样一段
【强制】不要在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。
正例:
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if (删除元素的条件) {
iterator.remove();
}
}
反例:
List<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
for (String item : list) {
if ("1".equals(item)) {
System.out.println(item);
list.remove(item);
}
}
尝试了一下,按直觉来看,反例应该会抛出一个ConcurrentModificationException,然而并没有。当把1换成2的时候,就会抛出异常。这真的很令人奇怪
查看ArrayList的源码中关于迭代器的部分
/**
* An optimized version of AbstractList.Itr
*/
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;
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
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];
}
。。。
}
curse保存着下一个返回的元素的索引。当remove第一个的时候,cursor变成了1,size也变成了1。因此调用hasNext()返回false,退出了循环。当list的size不是2的时候,就会抛出错误了