Iterator、Iteratable与ListIterator
- 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的更多相关文章
- 源码阅读—Iterator接口和LIstIterator接口
在继续看ArrayList源码之前,先了解Iterator接口和ListIterator接口,下篇文章详细讲解ArrayList是如何实现它们的. 我们知道,接口只是一种规范,当继承接口并实现其中的方 ...
- 详解 迭代器 —— Iterator接口、 ListIterator接口 与 并发修改异常
(请关注 本人"Collection集合"博文--<详解 Collection集合>) Iterator接口(迭代器): 概述: 对 collection 进行迭代的迭 ...
- Iterator之ListIterator简介
ListIterator是什么? (参考自百度百科) java中的ListIterator在Iterator基础上提供了add.set.previous等对列表的操作.但是ListIterator跟I ...
- Iterator和ListIterator区别
我们在使用List,Set的时候,为了实现对其数据的遍历,我们经常使用到了Iterator(迭代器).使用迭代器,你不需要干涉其遍历的过程,只需要每次取出一个你想要的数据进行处理就可以了. 但是在使用 ...
- Java容器类源码分析之Iterator与ListIterator迭代器(基于JDK8)
一.基本概念 迭代器是一个对象,也是一种设计模式,Java有两个用来实实现迭代器的接口,分别是Iterator接口和继承自Iterator的ListIterator接口.实现迭代器接口的类的对象有遍历 ...
- 09 Collection,Iterator,List,listIterator,Vector,ArrayList,LinkedList,泛型,增强for,可变参数,HashSet,LinkedHashSet,TreeSet
09 Collection,Iterator,List,listIterator,Vector,ArrayList,LinkedList,泛型,增强for,可变参数,HashSet,LinkedHas ...
- Java学习笔记之Iterator和ListIterator
原文:https://blog.csdn.net/GongchuangSu/article/details/51514380 Iterator接口是对collection进行迭代的迭代器,ListIt ...
- Iterator接口(迭代器)
目录 前言 原理 方法 异常 Iterator接口(迭代器) 前言 一般遍历数组都是采用for循环或者增强for,这两个方法也可以用在集合框架,但是还有一种方法是采用迭代器遍历集合框架,它是一个对象, ...
- 设计模式 笔记 迭代器模式 Iterator
//---------------------------15/04/26---------------------------- //Iterator 迭代器模式----对象行为型模式 /* 1:意 ...
随机推荐
- Ajax 随笔
例子:实现AJAX效果(投票例子) 后端代码 前端代码 原理是使用HTTP状态码204的特性(请求成功,但是不会返回内容,所以浏览器不会进行跳转) 例子:实现AJAX效果(投票例子2) 前端代码 原理 ...
- jquery 封装插件
如今做web开发,jquery 几乎是必不可少的,就连vs神器在2010版本开始将Jquery 及ui 内置web项目里了.至于使用jquery好处这里就不再赘述了,用过的都知道.今天我们来讨论下jq ...
- Qt_QString::split测试
1. #define GID_PREFIX "dr_" QString str = "dr__awedr4"; QString str1; QStringLis ...
- Android 获取本地外网IP、内网IP、计算机名等信息
一.获取本地外网IP public static String GetNetIp() { URL infoUrl = null; InputStream inStream = null; try { ...
- android调用照相机拍照获取照片并做简单剪裁
引用转载http://www.cnblogs.com/eyu8874521/archive/2012/07/20/2600697.html 效果: 客服端代码: package com.cn.lx ...
- Redis<一> 数据结构:String
). set key value : 将字符串值 value 关联到 key .如果 key 已经持有其他值, SET 就覆写旧值,无视类型. ). get key : 返回 key 所关联的字符串值 ...
- resin中关于url rewrite来传递jsessionid的问题
最近两天在项目中碰到,一个很奇怪的问题.同一个账号多次切换登录时,会出现这个账号的信息在session中找不到,虽然可以登录成功,但是之后这个用户信息好像没有保存到session中一样,或者是被改变了 ...
- Unity3D中人物模型的构成
1.动画: 2.骨骼: 就是一些 Transform 组件,没有其他组件,它们会根据动画的要求而进行运动. 3.皮肤: 其上的 SkinnedMeshRenderer 关联了 网格.骨骼.材质 三个组 ...
- Java知识集锦
Java知识集锦 一.Java程序基础 1.1 开发和运行环境 1.2 Java语言概述 二.Java语法基础 2.1 基础类型和语法 2.2 对象和类型 2.3 包和访问控制 三.数据类型及类型转换 ...
- centos7: svbversion版本的安装配置+tortoisesvn登录验证
centos7: svbversion版本的安装配置+tortoisesvn登录验证 命令工具:svnadmin create #创建版本库 hotcopy #版本库热备份 Islocks #打印所有 ...