Java ListIterator 与 Iterator 异同
一、概述
基于 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异常。
源码如下:ListItr是ArrayList的内部类
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 异同的更多相关文章
- JAVA中ListIterator和Iterator详解与辨析
在使用Java集 合的时候,都需要使用Iterator.但是java集合中还有一个迭代器ListIterator,在使用List.ArrayList. LinkedList和Vector的时候可以使用 ...
- Java学习之Iterator(迭代器)的一般用法 (转)
迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭代器通常被称为"轻量级"对象,因为创建它的代价 ...
- 【转】Java学习之Iterator(迭代器)的一般用法 (转)
[转]Java学习之Iterator(迭代器)的一般用法 (转) 迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭 ...
- Java学习之Iterator(迭代器)的一般用法
迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭代器通常被称为“轻量级”对象,因为创建它的代价小. Java中的I ...
- Java集合迭代器 Iterator分析
简介 迭代器是遍历容器的一种常用方法,它屏蔽了容器的实现细节,无需暴露数据结构内部,就可以对容器进行遍历,迭代器本身也是一种设计模式,迭代是一种特殊的遍历方式. Iterator 在java中,迭代器 ...
- Java学习之Iterator(迭代器)
迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭代器通常被称为“轻量级”对象,因为创建它的代价小. Java中的I ...
- LinkedList方法总结 ListIterator和Iterator的区别
LinkedList也像ArrayList一样实现了基本的接口,但是它执行某些从操作时比ArrayList更高效,但在随机访问方面要逊色一些.LinkedList中有一些方法虽然名字不同,但可以完成相 ...
- java中的Iterator接口
Iterator接口 Iterator接口也是Java集合框架的成员,但它与Collection系列.Map系列的集合不一样:Collection系列集合.Map系列集合主要用于盛装其他对象,而Ite ...
- atitit.session的原理以及设计 java php实现的异同
atitit.session的原理以及设计 java php实现的异同 1. session的保存:java在内存中,php脚本因为不能常驻内存,所以在文件中 1 2. php的session机制 1 ...
随机推荐
- windows下使用gcc完成头文件和目标文件编译
环境要求 安装了gcc win+r然后输入cmd , dos界面输入 gcc -v 查看有没有安装gcc 进入正题 新建 text.c文件键入如下代码: #include <stdio.h> ...
- angular-file-upload 在IE下使用的坑
如果在控件配置里面设置了queueLimit属性为1,就是队列文件个数为1,并且在<input>标签设置里multiple属性. 在IE浏览器上传附件的时候,浏览器会报错“SCRIPT50 ...
- js和JQuery中的获取宽、高、位置等方法整理
1.获取当前窗口宽度区别(需要注意的是用的window还是document)JQuery:console.log($(window).width()); //获取窗口可视区域的宽度 console.l ...
- 【树状数组 思维题】luoguP3616 富金森林公园
树状数组.差分.前缀和.离散化 题目描述 博艾的富金森林公园里有一个长长的富金山脉,山脉是由一块块巨石并列构成的,编号从1到N.每一个巨石有一个海拔高度.而这个山脉又在一个盆地中,盆地里可能会积水,积 ...
- 主DNS服务-正向解析
环境 准备最少两台主机 一台当DNS服务器,一台当客户机 如:192.168.43.7这台主机当DNS服务器,192.168.43.6这台主机当客户机 安装DNS服务 yum install -y b ...
- windows2012安装sql2012报错
一. 处理
- Verilog学习笔记基本语法篇(二)·········运算符
Verilog HDL的语言的运算符的范围很广,按照其功能大概可以分为以下几类: (1)算术运算符 +,-,*,/,% 优先顺序 !~ * / % + - << > ...
- pytorch遇到的问题:RuntimeError: randperm is only implemented for CPU
由此,我们找到sample.py,第51行如下图修改
- 【转】DCOM远程调用权限设置
原文:https://blog.csdn.net/ervinsas/article/details/36424127 最近几天被搞得焦头烂额,由于DCOM客户端程序是在32位系统下开发的,调试时DCO ...
- 【bzoj4804】欧拉心算 欧拉函数
题目描述 给出一个数字N 输入 第一行为一个正整数T,表示数据组数. 接下来T行为询问,每行包含一个正整数N. T<=5000,N<=10^7 输出 按读入顺序输出答案. 样例输入 1 1 ...