我在學習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
*/