我在学习Iterator时的一个误区:当使用Iterator()或ListIterator()方法生成迭代器对象时,迭代器对象指向第一个元素。
1、事实上,当使用Iterator()或ListIterator()方法生成迭代器对象时,迭代器对象不指向任何元素。
Iterator接口的部分实现如下:
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];
}
}
当使用Iterator()方法生成一个迭代器对象时,当前下标lastRet = -1;因此此时迭代器不指向任何元素,因此,如果在调用next()之前执行remove(),是不合法的操作。
2、我在查ListIterator()的说明文档时,有这样一段说明文字:它的游标位置总是位于previous()返回的元素和调用next()的元素之间。
我对这个模型不是很理解,因为参照Iterator(),cursor应该是指向元素的,为什么会位于元素之间,所以再去查看代码,结果发现类ListItr继承自类Itr,即类Itr的数据域cursor和lastRetcursor在ListIterator()中也是存在的,且hasNext()、next()这两个方法都没有重写:
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
super();
cursor = index;
}
public boolean hasPrevious() {
return cursor != 0;
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor - 1;
}
@SuppressWarnings("unchecked")
public E previous() {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i;
return (E) elementData[lastRet = i];
}
}
所以,ListIterator的结构和Iterator的结构是差不多的;
它的游标位置总是位于previous()返回的元素和调用next()的元素之间。这句话大概是为了方便对previous()和next这些方法的理解。
事实上,next()返回的是下标为cursor的元素,这一项是和Iterator保持一致的,pervious()返回的是下标为lastRet的元素,即下标为cursor-1的元素(当前元素)。
下面是一个例子:
在调用next()函数之前就调用previousIndex()和nextIndex()方法;
调用next()函数之前,lastRet=-1,cursor=0
因此第一行输出为-1 0
public static void main(String[] args) {
ArrayList<String> str = new ArrayList<String>();
for (int i = 0; i < 10; i++) {
str.add("string"+i);
}
ListIterator<String> it = str.listIterator();
while(it.hasNext()) {
//这里在调用next()函数之前就调用previousIndex()和nextIndex()方法;
//调用next()函数之前,lastRet=-1,cursor=0
//因此第一行输出为-1 0
System.out.println(it.previousIndex()+" "+it.nextIndex());
it.next();
}
System.out.println(it.previousIndex()+" "+it.nextIndex());
System.out.println(str);
}
/*Output
*-1 0
*0 1
*1 2
*2 3
*3 4
*4 5
*5 6
*6 7
*7 8
*8 9
*9 10
*/