Java Iterator ListIterator 理解

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

相关文章
相关标签/搜索