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];