一、 Iterator 常用操作 next hasNext remove

先上源码:JDK8 简化版本,用于说明问题

 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 public boolean hasNext() {
return cursor != size;
} public E next() {
int i = cursor;
Object[] elementData = ArrayList.this.elementData;
cursor = i + 1;
return (E) elementData[lastRet = i];
} public void remove() {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
} }

约定: Iterator  it = xxx.iterator();

疑惑1: 为什么不像 c++ 中 iterator 直接 *it 就可以获取当前值,java必须要 Object obj = it.next();

答:查看源码发现 调用 next 函数有两个作用,一个是获取当前 cusor 指向位置的元素,另一个是指针cusor 后移,并且 赋值 lastRet 变量(这里很关键)

疑惑二:为什么数组的最后一个元素进行 hasNext 返回真?

答:在迭代器中 可访问范围为 [0, size] 不是 [0, size)。因此传统意义数组的最后一个元素的下一个是 array[size], 尽管这个是无意义的,但是在迭代器中算一个特殊迭代器(类似 C++ . iterator.end() )

疑惑三:为什么删除元素不可以这么写?

 while(it.hasNext()){
  it.remove();
  it.next();
}

答:查看疑问一答中,next函数会赋值变量 lastRet ,这个变量对于 remove 函数相当重要。 因此在首次进入 while 循环的时候, laseRet = -1 (默认状态),因此不能直接进行 remove ,数组越界。

所以正确的应该是

 while(it.hasNext()){
it.next();
it.remove();
}

二、 ListIterator 中 lastIndex previousIndex previous

先上源码:JDK8 简化版本,用于说明问题

      public boolean hasPrevious() {
return cursor != 0;
} public int nextIndex() {
return cursor;
} public int previousIndex() {
return cursor - 1;
} public E previous() {
int i = cursor - 1;
Object[] elementData = ArrayList.this.elementData;
cursor = i;
return (E) elementData[lastRet = i];
}

疑惑一: 如何获取正确的 前一个元素的下标值和后一个元素的下标值?

答:先看一段代码:

 public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>(Arrays.asList(4, 5, 6, 7, 8));
ListIterator<Integer> it = list.listIterator();
System.out.println(it.previousIndex());
System.out.println(it.nextIndex());
}
//output
-1
0

显然输出并不正确,我们期望得到的是 -1 1

解释这个现象看源码,我们发现

① previousIndex 和 nextIndex 只能使用在后向移动的迭代器中,尽管ListIterator 是一个双向迭代器

② previousIndex 和 nextIndex 返回值依赖于 cursor 当前的数值,因此 上面代码中 cursor=0,所以 得出错误结果。要想获取下一个索引的正确之,我们需要 调用一次 next 函数帮助我们调整 cursor

这样即可获取我们期望的数值:

 public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>(Arrays.asList(4, 5, 6, 7, 8));
ListIterator<Integer> it = list.listIterator();
System.out.println(it.previousIndex());
it.next();
System.out.println(it.nextIndex());
}
//output 
-1
1

注: previous 和 next 函数中 cusor 移动不一样,

next函数是获取了当前值但是 cursor 已经移动到了下一个,相当于 return array[cursor++];

previous 函数是移动到前一个并且获取值   ,相当于 return array[--cursor];

												

Java Iterator ListIterator 理解的更多相关文章

  1. Java Iterator, ListIterator 和 foreach语句使用

    Java Iterator, ListIterator 和 foreach语句使用 foreach语句结构: for(part1:part2){part3};  part2 中是一个数组对象,或者是带 ...

  2. JAVA中ListIterator和Iterator详解与辨析

    在使用Java集 合的时候,都需要使用Iterator.但是java集合中还有一个迭代器ListIterator,在使用List.ArrayList. LinkedList和Vector的时候可以使用 ...

  3. java:集合输出Iterator,ListIterator,foreach,Enumeration

    //集合输出,集合的四种输出 Iterator, ListIterator, foreach, Enumeration 只要碰到集合,第一输出选择是Iterator类. Iterator<E&g ...

  4. Java 集合深入理解(8):AbstractSequentialList

    点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 今天有点无聊,来学学 AbstractSequentialList 解解闷 吧! AbstractSequentialLi ...

  5. Java 集合深入理解(7):ArrayList

    点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 今天心情有点美丽,学学 ArrayList 放松下吧! 什么是 ArrayList ArrayList 是 Java 集合 ...

  6. Java 集合深入理解(6):AbstractList

    点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 今天心情比天蓝,来学学 AbstractList 吧! 什么是 AbstractList AbstractList 继承自 ...

  7. Java 集合深入理解(4):List<E> 接口

    点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 蓝瘦!香菇! 连着加班几天,醉了.学学 List 放松下! 在 Java 集合深入理解:Collection 中我们熟悉了 ...

  8. 源码(08) -- java.util.ListIterator<E>

    java.util.ListIterator<E> 源码分析(JDK1.7) ------------------------------------------------------- ...

  9. 关于java中Stream理解

    关于java中Stream理解 Stream是什么 Stream:Java 8新增的接口,Stream可以认为是一个高级版本的Iterator.它代表着数据流,流中的数据元素的数量可以是有限的, 也可 ...

随机推荐

  1. 折半查找——Java实现

    一.查找思想 折半查找 也称为二分查找,是一种效率较高的查找方法,查找时要求表中的节点按关键字的大小排序,并且要求线性表顺序存储. 首先用要查找的关键字值(key)与中间位置结点的关键字值(arr[m ...

  2. 数组和矩阵(2)——Reshape the Matrix

    In MATLAB, there is a very useful function called 'reshape', which can reshape a matrix into a new o ...

  3. CRM——销售与客户

    一.销售与客户——表结构 1.客户类型 (1)公共客户(公共资源) 必备条件:没有报名: 在必备条件满足的情况下,满足以下任意条件都是公共客户: 3天没有跟进:15天没有成单. (2)我的客户 原销售 ...

  4. scss-嵌套属性

    使用scss不但可以实现选择器的嵌套,属性也可以进行嵌套. 首先看一段代码实例: nav { border-style: solid; border-width: 1px; border-color: ...

  5. 检查SQL Server 2005的索引密度和碎片信息(转)

    查询数据库中所有表的索引密度和碎片信息,以便为索引的重建和整理提供依据,也可以参考DBCC SHOWCONTIG,通常FRAGMENTATIOIN在30%以上建议重建,否则建议整理 SELECT i. ...

  6. 避免Autoclose和Autoshrink选项

    避免Autoclose和Autoshrink选项发布日期:2001年12月18日 问题:我在Microsoft SQL Server 2000资源工具包中读到了一个用于就应当避免使用的选项对所有数据库 ...

  7. 基于k8s的ES集群定期删除索引

    apiVersion: batch/v1beta1 kind: CronJob metadata: name: elasticsearch namespace: elasticsearch label ...

  8. 【CentOS】在Centos7 下无图形界面安装 Oracle11g

    目标 - 在虚拟机CentOS7中无图形界面安装Oracle11G R2版本 ① 系统要求以及准备 1. 物理内存不小于1G: 查看方式: # grep MemTotal /proc/meminfo ...

  9. asp.net反射的运用

    反射的用途:    (1)使用Assembly定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例.     (2)使用Module了解包含模块的程序集以及模块中的 ...

  10. hdu-4288 Coder---线段树+离线处理&离散化

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4288 题目大意: 维护一个有序数列{An},有三种操作: 1.添加一个元素. 2.删除一个元素. 3 ...