itr.hasNext():通过判断 cursor(游标) != size(长度)来决定是否结束循环,cursor(游标) 初始是0 每次经过 itr.next() +1;当cursor==size时 会跳出循环;
itr.next(): 看源代码可以发现每次在next()调用后,都会先调用checkForComodification()这个方法;
checkForComodification(): 主要作用是判断itr迭代器数据是否和list一致,
有两个参数,
第一个 modCount 集合结构变动次数,如:一开始你add调用了7次,那么这个数就是7,
第二个 expectedModCount 在调用iterator()方法时,初始化值等于modCount ,
这个方法判断当 modCount != expectedModCount 时 抛出异常ConcurrentModificationException,如果你调用迭代器的remove方法,expectedModCount 会重新赋值,但是你调用的是list的remove方法,那么modCount 就会+1 而expectedModCount 不变,这就会造成 modCount != expectedModCount;
//第二种删除方式 for(int i = 9;i>=0;i--){//使用倒序删除方式同样不会发生异常 list.get(i); list.remove(i); }ArrayList中的remove有两个同名方法,只是入参不同,这里看的是入参为Object的remove方法)是怎么实现的:
public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } 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; // Let gc do its work }可以看到会执行System.arraycopy方法,导致删除元素时涉及到数组元素的移动。所以将元素从数组中删除,并且将后一个元素移动至当前位置,导致下一次循环遍历时后一个字符串并没有遍历到,所以无法删除。针对这种情况可以倒序删除的方式来避免:
新闻热点
疑难解答