Java Iterator ListIterator 理解
一、 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 理解的更多相关文章
- Java Iterator, ListIterator 和 foreach语句使用
Java Iterator, ListIterator 和 foreach语句使用 foreach语句结构: for(part1:part2){part3}; part2 中是一个数组对象,或者是带 ...
- JAVA中ListIterator和Iterator详解与辨析
在使用Java集 合的时候,都需要使用Iterator.但是java集合中还有一个迭代器ListIterator,在使用List.ArrayList. LinkedList和Vector的时候可以使用 ...
- java:集合输出Iterator,ListIterator,foreach,Enumeration
//集合输出,集合的四种输出 Iterator, ListIterator, foreach, Enumeration 只要碰到集合,第一输出选择是Iterator类. Iterator<E&g ...
- Java 集合深入理解(8):AbstractSequentialList
点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 今天有点无聊,来学学 AbstractSequentialList 解解闷 吧! AbstractSequentialLi ...
- Java 集合深入理解(7):ArrayList
点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 今天心情有点美丽,学学 ArrayList 放松下吧! 什么是 ArrayList ArrayList 是 Java 集合 ...
- Java 集合深入理解(6):AbstractList
点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 今天心情比天蓝,来学学 AbstractList 吧! 什么是 AbstractList AbstractList 继承自 ...
- Java 集合深入理解(4):List<E> 接口
点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 蓝瘦!香菇! 连着加班几天,醉了.学学 List 放松下! 在 Java 集合深入理解:Collection 中我们熟悉了 ...
- 源码(08) -- java.util.ListIterator<E>
java.util.ListIterator<E> 源码分析(JDK1.7) ------------------------------------------------------- ...
- 关于java中Stream理解
关于java中Stream理解 Stream是什么 Stream:Java 8新增的接口,Stream可以认为是一个高级版本的Iterator.它代表着数据流,流中的数据元素的数量可以是有限的, 也可 ...
随机推荐
- 破解jar包5步搞定,jira7.9.2操作成功,附github代码库
1,从要破解的程序中拷贝.jar包文件,运行1_jar.sh将其解压.以jira7.9.2为例: $install_dir\JIRA\atlassian-jira\WEB-INF\lib\atlass ...
- scss-比较运算符
与JavaScript类似,scss中也有比较运算符,下面就分别做一下介绍. 一.==相等和!=不相等运算符: 此运算符用来判断两个操作数是否相等. 特别说明: 上面两个运算符,支持类似于JavaSc ...
- 【Mood-15】DailyBuild 1月
keywords: AsyncImageLoader universal-image-loader 2015-01-07 AsyncImageLoader:异步动态加载网络图片 类似listview ...
- visual studio code配置项
// 通过将设置放入设置文件中来覆盖设置. { //-------- 编辑器配置 -------- // 控制字体系列. "editor.fontFamily": "Co ...
- 【Leetcode】【Easy】Symmetric Tree
Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). For e ...
- 笨办法学Python(四十)
习题 40: 字典, 可爱的字典 接下来我要教你另外一种让你伤脑筋的容器型数据结构,因为一旦你学会这种容器,你将拥有超酷的能力.这是最有用的容器:字典(dictionary). Python 将这种数 ...
- MySQL学习(一) 数据表基本操作
创建数据库:create database db_name 查看数据库结构:show create database db_name 删除数据库:drop database db_name 查看数据库 ...
- iTunes备份路径,iTunes默认备份路径,iTunes修改备份路径
1:当前iTunes版本: 2:帮助给出的答复: 3:修改的操作界面: 实际文件夹路径:
- django使用orm方式查询mogodb的某段时间的值
在使用djgango时,需要在数据表中过滤出在某段时间的内容,网上很多或者说Django的orm是针对mysql,且字段类型是datetime或者其他时间类型,使用__rang这个函数就可以查询某个时 ...
- NTP原理初步与配置
一.Ntp基本原理 Server和·Client之间的同步(C/S模式) 1.主机启动ntp daemon 2.Client向NTP Server 发送调较时间的申请 3.NTP Server发送标准 ...