Iterator接口(迭代器)
Iterator接口(迭代器)
前言
- 一般遍历数组都是采用for循环或者增强for,这两个方法也可以用在集合框架,但是还有一种方法是采用迭代器遍历集合框架,它是一个对象,实现了Iterator 接口或ListIterator接口。
- 迭代器,使你能够通过循环来得到或删除集合的元素。ListIterator 继承了Iterator,以允许双向遍历列表和修改元素。
原理
- 在获取迭代器的时候,会创建一个集合的副本。同时会创建一个指针指向迭代器迭代集合的其实位置。
方法
- hasNext() :该方法会判断集合对象是否还有下一个元素,如果已经是最后一个元素则返回false。
- next():把迭代器的指向移到下一个位置,同时,该方法返回下一个元素的引用。
- remove() 从迭代器指向的集合中移除迭代器返回的最后一个元素。
public class Test{
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
list.add("Hello");
list.add("World");
list.add("!");
Iterator<String> ite = list.iterator();
//判断下一个元素之后是否有值
while(ite.hasNext()){
System.out.println(ite.next());
}
}
}
异常
ConcurrentModificationException异常
异常名:并发修改异常
产生原因:在使用迭代器遍历集合元素的同时对集合元素进行了操作时抛出此异常
解决办法:
使用普通for循环遍历
使用List特有的迭代器遍历
public class Test {
public static void main(String[] args) {
Collection<String> c = new ArrayList<String>();
c.add("张三");
c.add("李四");
c.add("王五");
Iterator<String> it = c.iterator();
while(it.hasNext()){
//必须是接收it.next(),不然会死循环。
Object obj = it.next();
String s = (String)obj;
if(s.contains("李四")){
// 最后会报ConcurrentModificationException异常
c.add("王五");
}
System.out.println(s);
}
}
}
使用foreach也会出现同样的异常:
}
for (Object object : c) {
String s = (String)object;
if (s.contains("李四")) {
c.add("王五");
}
System.out.println(s);
}
因为foreach遍历的本质就是使用iterator迭代器遍历。
注意:
在迭代的时候是可以删除元素的。因为会使用iterator中的remove。
看一下ArrayList中iterator重写的源码就明白了。
源码:
public Iterator<E> iterator() {
return new Itr();
}
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();
}
}
在ArrayList内部定义了一个内部类Itr,该类实现了Iterator接口。
在Itr中,有三个变量分别是
cursor:表示下一个元素的索引位置
lastRet:表示上一个元素的索引位置
expectModCount:预期被修改的次数
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();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
在执行remove操作时,会先执行checkForComodification(),判断集合的修改次数是否合法,然后会执行ArrayList的remove()方法,该方法会将modCount值加1,这里我们将expectedModCount=modCount,使之保持统一。
iterator和for循环的区别:
从数据结构角度分析,for循环适合访问顺序结构,可以根据下标快速获取指定元素.而Iterator适合访问链式结构,因为迭代器是通过next()来定位的.可以访问没有顺序的集合.
以上
@Fzxey
Iterator接口(迭代器)的更多相关文章
- Iterator接口(迭代器)的使用
Iterator接口(迭代器) 前言 在程序开发中,经常需要遍历集合中的所有元素.针对这种需求,JDK专门提供了一个接口java.util.Iterator.Iterator接口也是Java集合中的一 ...
- Java之集合初探(二)Iterator(迭代器),collections,打包/解包(装箱拆箱),泛型(Generic),comparable接口
Iterator(迭代器) 所有实现了Collection接口的容器都有一个iterator方法, 用来返回一个实现了Iterator接口的对象 Iterator对象称作迭代器, 用来方便的实现对容器 ...
- PHP:Iterator(迭代器)接口和生成器
迭代器 可在内部迭代自己的外部迭代器或类的接口.详情:http://php.net/manual/zh/class.iterator.php 接口摘要 Iterator extends Travers ...
- Java之Iterator接口(遍历单列集合的迭代器)
Iterator接口概述 在程序开发中,经常需要遍历集合中的所有元素.针对这种需求,JDK专门提供了一个接口java.util.Iterator . Iterator 接口也是Java集合中的一员,但 ...
- php迭代器Iterator接口
以前也看过迭代器Iterator接口,感觉不如yied好用,因此实际工作中并没有用到过. 今天看了一篇网上的博客(https://www.cnblogs.com/wwjchina/p/7723499. ...
- 详解 迭代器 —— Iterator接口、 ListIterator接口 与 并发修改异常
(请关注 本人"Collection集合"博文--<详解 Collection集合>) Iterator接口(迭代器): 概述: 对 collection 进行迭代的迭 ...
- Iterator接口介绍和迭代器的代码实现
定义:Iterator接口是Java集合框架中的一员. 作用:Collection接口与Map接口主要用于存储元素. 常用方法: boolen hasNext(); //判断游标右边是否还有元 ...
- SPL之Iterator(迭代器)接口
前言:SPL是用于解决典型问题(standard problems)的一组接口与类的集合. <?php /** * Class MyIterator * 在 PHP 中,通常情况下遍历数组使用 ...
- Collections+Iterator 接口 | Map+HashMap+HashTable+TreeMap |
Collections+Iterator 接口 1. Collections 是一个操作 Set.List 和 Map 等集合的工具类 Collections 中提供了大量方法对集合元素进行排序.查询 ...
随机推荐
- url 的正则表达式:path-to-regexp
概述 该工具库用来处理 url 中地址与参数,能够很方便得到我们想要的数据. js 中有 RegExp 方法做正则表达式校验,而 path-to-regexp 可以看成是 url 字符串的正则表达式. ...
- CodeForces 1151F Sonya and Informatics
题目链接:http://codeforces.com/problemset/problem/1151/F 题目大意: 给定长度为 n 的 01 序列,可以对该序列操作 k 次,每次操作可以交换序列中任 ...
- Python爬虫beautifulsoup4常用的解析方法总结
摘要 如何用beautifulsoup4解析各种情况的网页 beautifulsoup4的使用 关于beautifulsoup4,官网已经讲的很详细了,我这里就把一些常用的解析方法做个总结,方便查阅. ...
- git忽略文件不起作用时
开始我是直接进到仓库建立了.gitignore文件,再从仓库进入到项目add时总是会添加不需要添加的文件, 后来明白应该是在哪里提交在哪里创建.gitignore文件 git忽略文件操作步骤如下: 1 ...
- PLC 数据类型
类型 长度(位) 取值范围 描述 BOOL 1 0/1 布尔型 BYTE 8 0x00~0xFF 十六进制数 WORD 16 0~65535 无符号整数 DWORD 32 0~4294967295 无 ...
- 代码管理git 工具的话可以使用GitHub桌面端管理git、码云上的代码
git版本控制 廖雪峰老师的git教程 git是linus 1991年创建了开源的linux...已成为最大的服务器系统软件 集中式的版本控制器:CVS.SVN.ClearCase是IBM的收费软件 ...
- C#入门教程源码
C#入门教程源码 [日期:2019-01-26] 来源:51zxw.net 作者:zhangguofu [字体:大 中 小] 方法一:百度云盘下载地址: 链接:https://pan.baidu.c ...
- 相似度度量:欧氏距离与余弦相似度(Similarity Measurement Euclidean Distance Cosine Similarity)
在<机器学习---文本特征提取之词袋模型(Machine Learning Text Feature Extraction Bag of Words)>一文中,我们通过计算文本特征向量之间 ...
- docker报错:Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
在github上开到这样一条 于是 这两个选项换着来 具体怎么回事,咱也不知道,咱也不敢问 改完后蹭蹭的
- [APIO2017]商旅(floyd+分数规划+SPFA)
题解:首先肯定要跑最短路,而n<=100,所以可以用floyd,然后根据比值,很容易想到二分答案,然后再SPFA跑一遍负环,就能求出解了. #include<bits/stdc++.h&g ...