Iterator和ListIterator理解

我在學習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
	*/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章