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.它代表着数据流,流中的数据元素的数量可以是有限的, 也可 ...
随机推荐
- CSS文字有关属性
font-size|family|weight|style 大小字体加粗斜体 color|opacity 颜色透明度 height+line-height:垂直居中 overflow:hidden|v ...
- 关于asp.net网站中web.config的配置
1.Session生命周期配置 2.连接默认错误页 实例说明:在一些网站中,当网络地址发生错误时,通常会自动跳转到一个页面,并在该页面显示错误信息,此功能也可以通过配置web.config文件配置实现 ...
- Java开发高性能网站需要关注的事
转自:http://www.javabloger.com/java-development-concern-those-things/ 近期各家IT媒体举办的业内技术大会让很多网站都在披露自己的技术内 ...
- 16_AOP入门准备_Jdk动态代理模式
[工程截图] [PersonDao.java] package com.HigginCui.daoProxy; //目标类接口 public interface PersonDao { public ...
- Linux学习笔记之Linux第一课-基本介绍
Linux简介 Linux内核最初只是由芬兰人李纳斯·托瓦兹(Linus Torvalds)在赫尔辛基大学上学时出于个人爱好而编写的. Linux是一套免费使用和自由传播的类Unix操作系统,是一个基 ...
- 架构蓝图--软件架构 "4+1" 视图模型
引言 我们已经看到在许多文章和书籍中,作者欲使用单张视图来捕捉所有的系统架构要点.通过仔细地观察这 些图例中的方框和箭头,不难发现作者努力地在单一视图中表达超过其表达限度的蓝图.方框是代表运行的程序吗 ...
- django模板templates详解(二)
1 总体结构 Django是MTV结构,即:Model, Template, View Model:定义数据的存储格式,并且提供了数据库访问的API. View:定义那些数据被显示,是业务逻辑处理 ...
- day3 函数、递归、及内置函数
请查看我的云笔记链接: http://note.youdao.com/noteshare?id=7d5aa803981ae4375a1f648f48e7ade3&sub=5DFD553A6C5 ...
- 如何使用Putty登录安装在VirtualBox里的ubuntu
我是在Windows操作系统里用VirtualBox安装了ubuntu操作系统. 在VirtualBox里操作ubuntu的终端不是很方便,比如我想在Windows里复制一些命令到ubuntu的终端执 ...
- selenium启动不了浏览器或者启动后不会写入网址,先更新下浏览器驱动
平时自动化习惯用Chrome浏览器.有几个月没用selenium启动IE和Firefox,今天跑兼容性测试,需要验证其他浏览器.结果遇到两个异常: 1 IE启动不了,直接报错. 2 Firefox启动 ...