迭代器是通过内部的一个元素(即cursor(光标))来存储索引,另一个元素(lastRet(最近的使用的,大概如此意))来给予add和remove权限,具体实现如下:
先说初代的迭代器
他有的方法为next()、remove()、和hasNext()
首先光标定义在原始的初代迭代器中,默认值为零,lastRet值初始化为-1,然后每当调用一次next函数,则将先将光标内值存入lastRet中,然后再将光标下移一位,即加一,此时可调用一次remove()函数,删除光标前一位的元素,调用完毕将lastRet设置为-1,此时remove()不再可用,等待下一次被赋大于等于零的值。
整个逻辑可以理解为:我的下一个是某某某,然后,移除我
再说ListIterator,由初代的迭代器派生而来
他有的方法为:next()、previous()、hasNext()、hasPrevious()、nextIndex()、previousIndex()、add()、set()、remove()
会移动光标的方法:next()后移、previous()前移、add()将元素插入到当前光标前,然后光标后移,以保持依旧指向原一元素,不后移就会使光标正好指向刚加入的元素,
!!!直接操作并改动cursor(光标)的方法有,next()、previous()、add()
源码示例:
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];
}
!!!只调用光标不改动的方法有,hasNext()、hasPrevious()、nextIndex()、previousIndex()
!!!依赖lastRet的方法有set()、remove()
源码示例:
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.set(lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
remove()和add()会将lastRet()置为-1,即,使lastSet不可用
会将lastRet置为可用的方法有next()、previous()
next()后,remove和set会操作光标前一个的元素,
而previous()后,remove和set会操作目前光标所指的元素,
也就是说,先previous再next(set会操作在这两个操作前的初始元素的前一位的元素)和先next再previous(set会操作在这两个操作前的初始元素),然后再调用set或remove方法结果是不同的,
总得来说:remove()和set()方法依赖于next 和previous方法将lastRet设置为有用状态