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 ...
随机推荐
- shell脚本,提取ip地址和子网掩码,和查外网ip地址信息。
#提取IP地址和子网掩码 [root@localhost ~]# ifconfig eth0|grep 'inet addr'|awk -F'[ :]+' '{print $4"/& ...
- 人脸识别中的检测(在Opencv中加入了QT)
#include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include & ...
- CF-1110 (2019/02/08)
CF-1110 A. Parity 快速幂的思想,考虑最后一位即可 #include <bits/stdc++.h> using namespace std; typedef long l ...
- 【动态规划】bzoj1044: [HAOI2008]木棍分割
需要滚动优化或者short int卡空间 Description 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍 ...
- 主DNS服务-反向解析
上篇说了主DNS正向解析 当中是有个小问题的,什么问题呢? 试问当我们输入wwww或ww或更多w的时候它还能解析出来吗? 或者不输入w的时候还能解析吗? 上篇没有定义是解析不了的,怎么定义呢?很简单, ...
- Python数据类型(简单入门)
数据类型(预了解) 1.数字类型 整型:int 即不带小数点的数,通常用来标识年龄,账号,身份证号,等级等整数. 浮点型:float 即带有小数点的数,通常用来标记身高,体重,科学计算等有小数点的数. ...
- LeetCode(102) Binary Tree Level Order Traversal
题目 Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to rig ...
- Spring,Mybatis,Springmvc框架整合项目(第二部分)
一.创建数据库表 打开Navicat Premium,点击左上角连接,选择mysql 输入你的数据库用户名和密码信息,可以先点击下测试连接,如果显示连接成功,说明能连接到数据库,然后点击确定.如果 ...
- MFC中关于子进程创建和关闭操作
创建子进程 PROCESS_INFORMATION ProcessInfo; STARTUPINFO StartupInfo; //This is an [in] parameter ZeroMemo ...
- luogu3809 后缀排序 后缀数组
ref and 挑战程序设计竞赛. 主要是发现自己以前写得代码太难看而且忘光了,而且我字符串死活学不会啊,kmp这种东西我都觉得是省选+难度啊QAQ #include <iostream> ...