1、 Iterator 經常使用操做 next hasNext remove java
先上源碼:JDK8 簡化版本,用於說明問題c++
1 private class Itr implements Iterator<E> { 2 int cursor; // index of next element to return 3 int lastRet = -1; // index of last element returned; -1 if no such 4 5 public boolean hasNext() { 6 return cursor != size; 7 } 8 9 public E next() { 10 int i = cursor; 11 Object[] elementData = ArrayList.this.elementData; 12 cursor = i + 1; 13 return (E) elementData[lastRet = i]; 14 } 15 16 public void remove() { 17 ArrayList.this.remove(lastRet); 18 cursor = lastRet; 19 lastRet = -1; 20 } 21 22 }
約定: Iterator it = xxx.iterator(); 數組
疑惑1: 爲何不像 c++ 中 iterator 直接 *it 就能夠獲取當前值,java必需要 Object obj = it.next();函數
答:查看源碼發現 調用 next 函數有兩個做用,一個是獲取當前 cusor 指向位置的元素,另外一個是指針cusor 後移,而且 賦值 lastRet 變量(這裏很關鍵)this
疑惑二:爲何數組的最後一個元素進行 hasNext 返回真?spa
答:在迭代器中 可訪問範圍爲 [0, size] 不是 [0, size)。所以傳統意義數組的最後一個元素的下一個是 array[size], 儘管這個是無心義的,可是在迭代器中算一個特殊迭代器(相似 C++ . iterator.end() )指針
疑惑三:爲何刪除元素不能夠這麼寫?code
1 while(it.hasNext()){ 2 it.remove(); 3 it.next(); 4 }
答:查看疑問一答中,next函數會賦值變量 lastRet ,這個變量對於 remove 函數至關重要。 所以在首次進入 while 循環的時候, laseRet = -1 (默認狀態),所以不能直接進行 remove ,數組越界。blog
因此正確的應該是索引
1 while(it.hasNext()){ 2 it.next(); 3 it.remove(); 4 }
2、 ListIterator 中 lastIndex previousIndex previous
先上源碼:JDK8 簡化版本,用於說明問題
1 public boolean hasPrevious() { 2 return cursor != 0; 3 } 4 5 public int nextIndex() { 6 return cursor; 7 } 8 9 public int previousIndex() { 10 return cursor - 1; 11 } 12 13 public E previous() { 14 int i = cursor - 1; 15 Object[] elementData = ArrayList.this.elementData; 16 cursor = i; 17 return (E) elementData[lastRet = i]; 18 }
疑惑一: 如何獲取正確的 前一個元素的下標值和後一個元素的下標值?
答:先看一段代碼:
1 public static void main(String[] args) { 2 List<Integer> list = new ArrayList<Integer>(Arrays.asList(4, 5, 6, 7, 8)); 3 ListIterator<Integer> it = list.listIterator(); 4 System.out.println(it.previousIndex()); 5 System.out.println(it.nextIndex()); 6 }
//output
-1
0
顯然輸出並不正確,咱們指望獲得的是 -1 1
解釋這個現象看源碼,咱們發現
① previousIndex 和 nextIndex 只能使用在後向移動的迭代器中,儘管ListIterator 是一個雙向迭代器
② previousIndex 和 nextIndex 返回值依賴於 cursor 當前的數值,所以 上面代碼中 cursor=0,因此 得出錯誤結果。要想獲取下一個索引的正確之,咱們須要 調用一次 next 函數幫助咱們調整 cursor
這樣便可獲取咱們指望的數值:
1 public static void main(String[] args) { 2 List<Integer> list = new ArrayList<Integer>(Arrays.asList(4, 5, 6, 7, 8)); 3 ListIterator<Integer> it = list.listIterator(); 4 System.out.println(it.previousIndex()); 5 it.next(); 6 System.out.println(it.nextIndex()); 7 }
//output
-1
1
注: previous 和 next 函數中 cusor 移動不同,
next函數是獲取了當前值可是 cursor 已經移動到了下一個,至關於 return array[cursor++];
previous 函數是移動到前一個而且獲取值 ,至關於 return array[--cursor];