一、概述

基于 fail-fast 机制,我们知道对于ArrayList等集合在迭代过程中是不可进行结构修改操作的,唯一能使用的结构修改操作只有Iterator接口中的remove()方法。

java.util.ListIterator接口继承自Iterator接口,是专用于列表集合的迭代器,在 Iterator 的基础上,额外提供了 previous、nextIndex、add、set 等方法。

next、previous语义上的小问题

  • 迭代器中的next()方法不应该理解为返回下一个元素,而是返回当前元素,并将指针移向下一个
  • cursor永远指向下一个待返回的元素下标。
  • previous() 则是将指针向前移动一个位置后返回元素。

比如以下情况:

    // 对于 List{3,4,5}
ListIterator<Integer> listIterator = list.listIterator();
boolean isDo = false; //isDo保证只向前移动一次,否则会死循环
while(listIterator.hasNext()){
Integer i = listIterator.next();
if(i.equals(4)&&!isDo){
i = listIterator.previous();
isDo = true;
}
System.out.println(i);
}

最后输出:

    3
4 //因为equal(4)时指针已经指向5了, previous会导致指针重回4
//(而不是字面上想的当==4时,返回上一个3)
4
5

修改对迭代过程是否可见?

是否可见具体看类(暂未找到对比)。如 对于ArrayList来说,迭代器并未使用副本数组,因此修改是可见的(但需要一定操作,因为add方法添加元素后会把指针再往后移一位【即,若一直next的话,等于忽略了迭代过程中添加的元素】)

二、一些类对LisIterator实现详解

2.1 ArrayList 对 ListIterator 的实现

对于ArrayList对ListIterator的实现来说,并不是取消了fail-fast机制,而是调用迭代器来修改的话,每次修改后都令expectedModCount = modCount,因此不会报ConcurrentModificationException异常。

源码如下:ListItrArrayList的内部类

    private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
super();
cursor = index; //构建是可指定迭代开始下标,默认是0
} public boolean hasPrevious() { return cursor != 0; } /** 因为cursor始终指向下个元素下标 */
public int nextIndex() { return cursor; } public int previousIndex() { return cursor - 1; } /** 返回cursor-1的元素 */
@SuppressWarnings("unchecked")
public E previous() {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i;
return (E) elementData[lastRet = i]; //lastRet始终保存上次获取元素的下标
} /** 省略set源码,set方法用以设置lastRet元素 */ /** 添加方法*/
public void add(E e) {
checkForComodification(); try {
int i = cursor;
ArrayList.this.add(i, e); //将元素添加在当前元素后面,也就是cursor的位置
cursor = i + 1; //再将cursor+1,等于忽略刚添加的元素
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}

2.2 CopyOnWriteArrayList 对ListIterator的实现

对于CopyOnWriteArrayList,虽然有lisIterator方法,但实则不支持列表迭代器的结构修改方法,如add、remove等(直接抛UnsupportedOperationException),因为它 fail-safe机制本身就支持迭代过程中去修改集合。但修改是不可见的,具体参考CopyOnWriteArrayList对fail-safe实现

Java ListIterator 与 Iterator 异同的更多相关文章

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

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

  2. Java学习之Iterator(迭代器)的一般用法 (转)

    迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭代器通常被称为"轻量级"对象,因为创建它的代价 ...

  3. 【转】Java学习之Iterator(迭代器)的一般用法 (转)

    [转]Java学习之Iterator(迭代器)的一般用法 (转) 迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭 ...

  4. Java学习之Iterator(迭代器)的一般用法

    迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭代器通常被称为“轻量级”对象,因为创建它的代价小. Java中的I ...

  5. Java集合迭代器 Iterator分析

    简介 迭代器是遍历容器的一种常用方法,它屏蔽了容器的实现细节,无需暴露数据结构内部,就可以对容器进行遍历,迭代器本身也是一种设计模式,迭代是一种特殊的遍历方式. Iterator 在java中,迭代器 ...

  6. Java学习之Iterator(迭代器)

    迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭代器通常被称为“轻量级”对象,因为创建它的代价小. Java中的I ...

  7. LinkedList方法总结 ListIterator和Iterator的区别

    LinkedList也像ArrayList一样实现了基本的接口,但是它执行某些从操作时比ArrayList更高效,但在随机访问方面要逊色一些.LinkedList中有一些方法虽然名字不同,但可以完成相 ...

  8. java中的Iterator接口

    Iterator接口 Iterator接口也是Java集合框架的成员,但它与Collection系列.Map系列的集合不一样:Collection系列集合.Map系列集合主要用于盛装其他对象,而Ite ...

  9. atitit.session的原理以及设计 java php实现的异同

    atitit.session的原理以及设计 java php实现的异同 1. session的保存:java在内存中,php脚本因为不能常驻内存,所以在文件中 1 2. php的session机制 1 ...

随机推荐

  1. Bootstrap历练实例:分页状态

    分页的状态 下面的实例演示了上表中所讨论的 class .disabled..active 的用法: <!DOCTYPE html><html><head>< ...

  2. EXTJS中文乱码

    在<head>中加入 <meta http-equiv="Content-Type" content="text/html; charset=GB231 ...

  3. Quartz监听的端口

    上海移通短信网关:556重庆移动短信网关:557消息中心后台维护服务:558网页订单数据同步服务:559基础数据同步程序:560短信数据扣除服务:565基础数据维护服务:589推送数据抓取服务:222 ...

  4. 1008: ASCII码

    题目描述 相信大家一定都知道大名鼎鼎的ASCII码,这次给你的任务是输入数字(表示ASCII码),输出相对应的字符信息. 输入 第一行为一个整数T(1<=T<=1000).接下来包括T个正 ...

  5. CentOS7写汇编并编译运行汇编代码

    1.下载nasm编译器 下载地址是https://www.nasm.us/pub/nasm/releasebuilds/ wget https://www.nasm.us/pub/nasm/relea ...

  6. [LUOGU] P4767 [IOI2000]邮局

    https://www.luogu.org/problemnew/show/P4767 四边形不等式好题! 可以设f[i][j]表示前i个村庄,建了j个邮局的最小代价. 转移:f[i][j]=min{ ...

  7. 在/etc/crondtab中添加定时任务注意事项

    1 要添加用户名 2 要重启定时任务服务

  8. 【linux】【git】安装/升级Git 1.9.4

      因为yum源的最新版本是1.7.x,所以无法通过yum进行更新,下面描述如何通过编译源码进行安装 1.安装需要的依赖 第一步我们需要做的就是确认系统已经安装了编译git时需要的依赖.使用下面的安装 ...

  9. python datetime,time时间格式和用法

    我是转载的这个大神的   他的网址:https://www.cnblogs.com/wanglinjie/p/9226926.html #以下是time的方法 >>> import ...

  10. (转)UILabel常用属性

    Java代码 收藏代码 #import "ViewController.h" #import <CoreText/CoreText.h> @interface View ...