一、概述

基于 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实现

最新文章

  1. 统计项目的java代码总行数
  2. xcode 使用通用总结
  3. linux下如何导入导出MySQL数据库
  4. LLDB调试基本使用
  5. C# MD5 16进制MD5对称加密法
  6. centos es2.x安装
  7. 如何实现Linux下的U盘(USB Mass Storage)驱动
  8. PHP程序猿必备的七种武器
  9. MySQL增量订阅&amp;消费组件Canal POC
  10. (引用)!Unicode,GBK以及UTF8的联系和区别
  11. 最短路问题(Bellman/Dijkstra/Floyd)
  12. 如何停止处于stopping状态的windows服务
  13. dubbo框架原理
  14. 怎样将M4A音频格式转换成MP3格式
  15. javaBean转为json
  16. css 样式 文字过长 换行处理方法
  17. JDK的多线程与并发库
  18. LintCode-7-二叉树的序列化和反序列化
  19. PowerDesigner 建表语句没出现字段描述
  20. Too Many Open Files的错误

热门文章

  1. bootstrap 两端对齐的导航
  2. js常用技巧汇总
  3. Linux网卡设置为网桥模式
  4. Xcode 6 创建 Objective-C category
  5. ios之UIScrollView
  6. python virtualenv学习
  7. 【简●解】 LG P2730 【魔板 Magic Squares】
  8. linux中添加一个用户到指定用户组的两种方式,修改一个用户到指定用户组的一种方式
  9. Web框架之Django_08 重要组件(form组件、cookie和session组件)
  10. ASP.NET MVC中如何在当前页面上弹出另外一个页面