• Iteratable:
public interface Iterable<T> {

    Iterator<T> iterator();

    default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
} default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
    • Iteratable接口提供了iterator()方法。
    • Collection接口继承了Iteratable,由实现Collection的ArrayList、Hashset等来实现方法。
  • Iterator:

public interface Iterator<E> {

    boolean hasNext();

    E next();

    default void remove() {
throw new UnsupportedOperationException("remove");
} default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
    • Iterator接口在ArrayList、LinkedList等类中都有内部类实现
    • Iterator接口的不当使用会导致抛出ConcurrentModificationException:
    List<String> famousList = new ArrayList<>();
famousList.add("Sheldon");
famousList.add("Sherlock");
famousList.add("Batman");
famousList.add("Optimus Prime"); for (String famous :
famousList) {
famousList.remove(famous);
}

上面的代码之所以会抛出ConcurrentModificationException异常的原因:

  • 增强for循环其实在编译生成字节码后会发现,就是转化为通过调用iterator的hasNext()、next()函数来遍历集合,查看ArrayList的iterator的实现代码:
    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
int expectedModCount = modCount; public boolean hasNext() {
return cursor != size;
} @SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
} public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification(); try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
} @Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
} final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}

从以上代码可知,当调用next()函数的时候,会先调用checkForComodification函数来检查集合的modCount与expectedModCount是否相等,若不相等则抛出错误。来到这里就能知道,在使用iterator遍历集合的时候,使用集合的remove、add等函数,就会导致modCount和expectedModCount不一致,从而导致异常抛出。

  • 正确的做法:
    Iterator<String> iterator = famousList.iterator();
for (;iterator.hasNext();){
String famous=iterator.next();
System.out.println(famous);
if ("Batman".equals(famous)){
iterator.remove();
break;
}
}
System.out.println(famousList.size());

或者:

    for (int i = 0; i < famousList.size(); i++) {
System.out.println(famousList.get(i));
if ("Batman".equals(famousList.get(i))){
famousList.remove(famousList.get(i));
break;
}
}
System.out.println(famousList.size());
  • ListIterator:
public interface ListIterator<E> extends Iterator<E> {

    boolean hasNext();

    E next();

    //判断cursor前是否有元素
boolean hasPrevious(); //获得cursor前一个元素,并且cursor后退一位
E previous(); //返回cursor元素的index
int nextIndex(); //返回cursor前一个元素的index
int previousIndex(); void remove(); //更新上一次调用next、previous返回的元素,也就是iterator最后一次操作的元素,没有调用next、previous前调用的话会抛出IllegalStateExceptiony异常
void set(E e); //向cursor前插入元素
void add(E e); }
  • ListIterator由实现List接口的集合类通过以下两种方法返回:
    public ListIterator<E> listIterator() {
return new ListItr(0);
} //返回指定cursor位置的listIterator
public ListIterator<E> listIterator(int index) {
if (index < 0 || index > size)
throw new IndexOutOfBoundsException("Index: "+index);
return new ListItr(index);
}

相比Iterator,多了add、set以及previous等方法。

Iterator、Iteratable与ListIterator的更多相关文章

  1. 源码阅读—Iterator接口和LIstIterator接口

    在继续看ArrayList源码之前,先了解Iterator接口和ListIterator接口,下篇文章详细讲解ArrayList是如何实现它们的. 我们知道,接口只是一种规范,当继承接口并实现其中的方 ...

  2. 详解 迭代器 —— Iterator接口、 ListIterator接口 与 并发修改异常

    (请关注 本人"Collection集合"博文--<详解 Collection集合>) Iterator接口(迭代器): 概述: 对 collection 进行迭代的迭 ...

  3. Iterator之ListIterator简介

    ListIterator是什么? (参考自百度百科) java中的ListIterator在Iterator基础上提供了add.set.previous等对列表的操作.但是ListIterator跟I ...

  4. Iterator和ListIterator区别

    我们在使用List,Set的时候,为了实现对其数据的遍历,我们经常使用到了Iterator(迭代器).使用迭代器,你不需要干涉其遍历的过程,只需要每次取出一个你想要的数据进行处理就可以了. 但是在使用 ...

  5. Java容器类源码分析之Iterator与ListIterator迭代器(基于JDK8)

    一.基本概念 迭代器是一个对象,也是一种设计模式,Java有两个用来实实现迭代器的接口,分别是Iterator接口和继承自Iterator的ListIterator接口.实现迭代器接口的类的对象有遍历 ...

  6. 09 Collection,Iterator,List,listIterator,Vector,ArrayList,LinkedList,泛型,增强for,可变参数,HashSet,LinkedHashSet,TreeSet

    09 Collection,Iterator,List,listIterator,Vector,ArrayList,LinkedList,泛型,增强for,可变参数,HashSet,LinkedHas ...

  7. Java学习笔记之Iterator和ListIterator

    原文:https://blog.csdn.net/GongchuangSu/article/details/51514380 Iterator接口是对collection进行迭代的迭代器,ListIt ...

  8. Iterator接口(迭代器)

    目录 前言 原理 方法 异常 Iterator接口(迭代器) 前言 一般遍历数组都是采用for循环或者增强for,这两个方法也可以用在集合框架,但是还有一种方法是采用迭代器遍历集合框架,它是一个对象, ...

  9. 设计模式 笔记 迭代器模式 Iterator

    //---------------------------15/04/26---------------------------- //Iterator 迭代器模式----对象行为型模式 /* 1:意 ...

随机推荐

  1. Ajax 随笔

    例子:实现AJAX效果(投票例子) 后端代码 前端代码 原理是使用HTTP状态码204的特性(请求成功,但是不会返回内容,所以浏览器不会进行跳转) 例子:实现AJAX效果(投票例子2) 前端代码 原理 ...

  2. jquery 封装插件

    如今做web开发,jquery 几乎是必不可少的,就连vs神器在2010版本开始将Jquery 及ui 内置web项目里了.至于使用jquery好处这里就不再赘述了,用过的都知道.今天我们来讨论下jq ...

  3. Qt_QString::split测试

    1. #define GID_PREFIX "dr_" QString str = "dr__awedr4"; QString str1; QStringLis ...

  4. Android 获取本地外网IP、内网IP、计算机名等信息

    一.获取本地外网IP public static String GetNetIp() { URL infoUrl = null; InputStream inStream = null; try { ...

  5. android调用照相机拍照获取照片并做简单剪裁

    引用转载http://www.cnblogs.com/eyu8874521/archive/2012/07/20/2600697.html 效果: 客服端代码:   package com.cn.lx ...

  6. Redis<一> 数据结构:String

    ). set key value : 将字符串值 value 关联到 key .如果 key 已经持有其他值, SET 就覆写旧值,无视类型. ). get key : 返回 key 所关联的字符串值 ...

  7. resin中关于url rewrite来传递jsessionid的问题

    最近两天在项目中碰到,一个很奇怪的问题.同一个账号多次切换登录时,会出现这个账号的信息在session中找不到,虽然可以登录成功,但是之后这个用户信息好像没有保存到session中一样,或者是被改变了 ...

  8. Unity3D中人物模型的构成

    1.动画: 2.骨骼: 就是一些 Transform 组件,没有其他组件,它们会根据动画的要求而进行运动. 3.皮肤: 其上的 SkinnedMeshRenderer 关联了 网格.骨骼.材质 三个组 ...

  9. Java知识集锦

    Java知识集锦 一.Java程序基础 1.1 开发和运行环境 1.2 Java语言概述 二.Java语法基础 2.1 基础类型和语法 2.2 对象和类型 2.3 包和访问控制 三.数据类型及类型转换 ...

  10. centos7: svbversion版本的安装配置+tortoisesvn登录验证

    centos7: svbversion版本的安装配置+tortoisesvn登录验证 命令工具:svnadmin create #创建版本库 hotcopy #版本库热备份 Islocks #打印所有 ...