• 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. HDU 2586 How far away ?(LCA在线算法实现)

    http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:给出一棵树,求出树上任意两点之间的距离. 思路: 这道题可以利用LCA来做,记录好每个点距离根结点的 ...

  2. LA 4329 乒乓比赛

    https://vjudge.net/problem/UVALive-4329 题意: 一条大街上住着n个兵乓球爱好者,经常组织比赛切磋技术.每个人都有一个不同的技能值ai.每场比赛需要3个人:两名选 ...

  3. html 画出矩形,鼠标弹起,矩形消失

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  4. Spring Boot 2.1.1.RELEASE 多数据源配置与使用

    有时候,一个系统的功能,需要两个或两个以上的数据库, 在Spring Boot 中要如何配置? How to? #primary primary.spring.datasource.jdbc-url= ...

  5. Python day10 global关键字、函数递归、匿名函数、map函数的用法详解

    1.global关键字 引用全局变量,在局部全局变量改变,也会改变,global相当于指针,将地址指向全局变量的name name='littlepage' def littepage(): glob ...

  6. Qt数据库_资料

    1. QT笔记_数据库总结(一)-rojian-ChinaUnix博客.html http://blog.chinaunix.net/uid-28194872-id-3631462.html (里面有 ...

  7. Java8 Lambda代码备份

    简单研究了一下,贴出来,相当于笔记 import java.lang.reflect.*; import java.util.ArrayList; import java.util.List; imp ...

  8. jsp动作之 forward

    forward说明了,就想当于php的include,require函数.(但是它是跳转.forward之前的数据都不会显示) 这么说你明白了吗.就是包含,说的好听点就是跳转,但是url地址栏却是没有 ...

  9. English trip V1 - 7.My dream car 我梦想的车 Teacher:Lamb Key: famous for

    中华In this lesson you will learn to describe an object(目标). 课上内容(Lesson) famous for   以…著称,闻名 国家(名词)  ...

  10. 关于floyd 打印路径的问题

    我们令    f[i][j]  表示从 i-->j的最短路上j前面的那个点. 显然初始化时  f[i][j]=i;  (这样的话先判断一下i是否能到达j好点) 更新条件时,当发现通过点k能使最短 ...