直接上代码:java
public class test { public static void main(String[] args) { List<Integer> list = new ArrayList<>(); for (int i = 0 ; i < 10 ; i++ ) { list.add(i); } Iterator<Integer> iterator = list.iterator(); int i = 0 ; while(iterator.hasNext()) { if (i == 3) { iterator.remove(); //报java.lang.IllegalStateException异常 } i ++; } System.out.println(list); } }
为何会报异常呢,经过一些查资料或者基础较好的读者知道只须要使用调用迭代器iterator.next()方法便可返回当前元素,因此只须要在remove()方法前面加上this
iterator.next();
注意这里有人会使用int x = iterator.next();这样来把当前的索引赋值而后再进行操做,其实这样是不必的,咱们来根据这个例子深刻的了解一下iterator的源码是如何实现的。spa
首先咱们调用的是list.iterator()方法来获取这个迭代器,固然list类并无实现这个方法,咱们最终是使用它的子类ArrayList来获取迭代器:code
/** * Returns an iterator over the elements in this list in proper sequence. * * <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>. * * @return an iterator over the elements in this list in proper sequence */ public Iterator<E> iterator() { return new Itr(); } /** * 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; Itr() {} 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]; } 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(); } }
能够看到,iterator()方法返回了一个Itr对象,接着下面,Itr是一个内部类,而且实现了Itertor接口。对象
回到咱们最初的问题,为何在迭代器中不用在不使用next()方法状况下进行remove操做会出错?咱们来看下remove()方法源码,blog
在remove方法第一行,便可看到:索引
if (lastRet < 0) throw new IllegalStateException();
当lastRet < 0的状况下,会抛出IllegalStateException异常,那么这个lastRet是什么呢,其实在Itr类就定义了这个lastRet变量,和它一块儿的还有cursor,expectedModCount;接口
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;
经过注释能够看到,lastRet就是上个元素的索引,默认是-1,因此直接调用迭代器的remove()方法会报错就是这个缘由,element
因此在上面的next()方法里,咱们能够看到这样的代码:rem
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];
它会把cursor游标赋值给i,而后进行+1操做,最后将lastRet赋值成i,因此lastRet就不是默认的-1了,而是会获得上个元素的索引,
因此综合上述的结论,在使用迭代器iterator.remove()方法前,必定先调用next()方法来给变量lastRet进行赋值操做。