集合:Iterator
why ? when ? how ? what ?
为什么需要集合呢?
在数据结构中链表、树、堆等一些操作都是由我们自己写的,这些操作是不是可以提取出来,以后要用就直接拿来用就好,这样非常方便。
Java 集合框架图

由上图我们可以看到,Java 集合主要分为两类:Collection 和 Map。
Collection 接口继承了 Iterable 接口。而 Iterable 接口中主要方法是 iterator();
public interface Iterable<T> {
/**
* Returns an iterator over elements of type {@code T}.
*
* @return an Iterator.
*/
Iterator<T> iterator();
}
废弃的接口:Enumeration
Enumeration 接口是JDK1.0时推出的,是最好的迭代输出接口,最早使用Vector(现在推荐使用ArrayList)时就是使用Enumeration接口进行输出。
Enumeration接口常用的方法有hasMoreElements()(判断是否有下一个值)和 nextElement()(取出当前元素),这些方法的功能跟Iterator类似,只是Iterator中存在删除数据的方法,而此接口不存在删除操作。
Iterator
Iterator 接口含有如下 4 个方法

看到 default 关键字,网上看了下是 jdk 1.8 出来的,就是接口中可以包含方法体。
fail-fast 机制是java集合中的一种错误机制。当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。例如:当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了;那么线程A访问集合时,就会抛出
ConcurrentModificationException异常,产生fail-fast事件。
for-each 的循环内部也是使用了 Iterator 来遍历Collection,它也调用了 Iterator.next(),所以在修改元素时会检查(元素的)变化并抛出 ConcurrentModificationException。
Iterator<Integer> iterator=list.iterator();
while (iterator.hasNext()){
list.remove(2);
System.out.println(iterator.next());
}
会抛出 currentModificationException 因为我们在使用 Iterator 对容器进行迭代的时候修改了容器。
如 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;//这个就是为了验证现在遍历的容器是不是没被修改过
}
modCount 是指集合修改次数
modCount 在 add, clear, remove 时都会被修改。
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
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();
}
}
在调用迭代器的 next、remove方法都会检查 modCount、expectedModCount 这两个的值是否相等。
如何解决 currentModificationException?
单线程:使用 Iterator 中的 remove 方法
多线程:
由于使用iterator对容器进行访问不需要获取锁,在多线程中就会造成当一个线程删除了元素,由于 modCount 是 AbstarctList 的成员变量,因此可能会导致在其他线程中modCount 和 expectedModCount值 不等。
static ArrayList<Integer> list = new ArrayList<Integer>();
public static void main(String[] args) {
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
Thread thread1 = new Thread(){
@Override
public void run() {
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()){
Integer integer = iterator.next();
System.out.println(integer);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
};
Thread thread2 = new Thread(){
@Override
public void run() {
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()){
Integer integer = iterator.next();
if(integer==2)
iterator.remove();
}
};
};
thread1.start();
thread2.start();
}

一般有2种解决办法:
1)在使用iterator迭代的时候使用synchronized或者Lock进行同步;
2)使用并发容器CopyOnWriteArrayList代替ArrayList和Vector。
参考
集合:Iterator的更多相关文章
- java集合-Iterator迭代
我们常常使用 JDK 提供的迭代接口进行 Java 集合的迭代. Iterator iterator = list.iterator(); while(iterator.hasNext()){ Str ...
- Java集合Iterator迭代器的实现
一.迭代器概述 1.什么是迭代器? 在Java中,有很多的数据容器,对于这些的操作有很多的共性.Java采用了迭代器来为各种容器提供了公共的操作接口.这样使得对容器的遍历操作与其具体的底层实现相隔离, ...
- 集合——iterator迭代器
Iterator接口: Iterator接口使用: 其中,集合Collection接口的定义也是使用多态,必须要创建它的子类对象才行,子类接口也是不能直接创建对象的(List接口): 其中wihle的 ...
- JAVA基础——集合Iterator迭代器的实现
一.迭代器概述 1.什么是迭代器? 在Java中,有很多的数据容器,对于这些的操作有很多的共性.Java采用了迭代器来为各种容器提供了公共的操作接口.这样使得对容器的遍历操作与其具体的底层实现相隔离, ...
- Java集合--Iterator和Enumeration比较
转载请注明出处:http://www.cnblogs.com/skywang12345/admin/EditPosts.aspx?postid=3311275 第1部分 Iterator和Enumer ...
- JAVA集合--Iterator接口
本文首发于cartoon的博客 转载请注明出处:https://cartoonyu.github.io/cartoon-blog 上一篇文章中我在集合元素的遍历中已经有涉及到I ...
- 对象转型、迭代器Iterator、Set集合、装箱与拆箱、基本数据类型与字符串的转换、TreeSet集合与对象
包的声明与定义 需要注意的是,包的声明只能位于Java源文件的第一行. 在实际程序开发过程中,定义的类都是含有包名的: 如果没有显式地声明package语句,创建的类则处于默认包下: 在实际开发中 ...
- 8.2.2 使用Java8增强的Iterator遍历集合元素
8.2.2 使用Java 8增强的Iterator遍历集合元素 Iterator接口方法 程序示例 Iterator仅用于遍历集合 Iterator必须依附于Collection对象 修改迭代变量的值 ...
- java集合(2)-Collection与Iterator接口
1 package com.j1803.collectionOfIterator; 2 import java.util.ArrayList; 3 import java.util.Collectio ...
随机推荐
- Killer Problem(暴力)
题意: 给定一个序列,每次询问l到r之间两个数差的绝对值的最小值. 分析: 开始以为是线段树离线处理,实际暴力就好! #include <map> #include <set> ...
- A Go library implementing an FST (finite state transducer)——mark下
https://github.com/couchbaselabs/vellum Building an FST To build an FST, create a new builder using ...
- Python: PS 滤镜--马赛克
本文利用 Python 实现PS 滤镜中的马赛克效果,具体的算法原理和效果可以参考之前的博客: http://blog.csdn.net/matrix_space/article/details/30 ...
- 10.05FZSZ Day2模拟总结
今天的题目难度比昨天小一些,但是太菜的我还是啥也不会. 今天的出题大佬是Heaplex,他的题目中倒是出现了ZZQ,不知道是否是本人? T1.a 期望得分30,实际得分30 这道题开场发现好像有什么小 ...
- 洛谷 P1351 联合权值 —— 树形DP
题目:https://www.luogu.org/problemnew/show/P1351 树形DP,别忘了子树之间的情况(拐一下距离为2). 代码如下: #include<iostream& ...
- mysql数据类型和java对应表(copy)
[说明] 资料来自:http://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-type-conversions.html My ...
- bzoj 1633: [Usaco2007 Feb]The Cow Lexicon 牛的词典【dp】
预处理出g[i][j]表示原串第i个匹配第j个单词需要去掉几个字母(匹配不上为-1) 设f[i]为i及之后满足条件要去掉的最少字母 倒着dp! f[i]初始为f[i+1]+1,转移方程为f[i]=mi ...
- HTML和JSP的不同及优缺点
HTML(Hypertext Markup Language)文本标记语言,它是静态页面,和JavaScript一样解释性语言,为什么说是解释性语言呢?因为,只要你有一个浏览器那么它就可以正常显示出来 ...
- (数论 欧拉筛法)51NOD 1106 质数检测
给出N个正整数,检测每个数是否为质数.如果是,输出"Yes",否则输出"No". Input 第1行:一个数N,表示正整数的数量.(1 <= N &l ...
- UVa 101 - The Blocks Problem STL
题目:给你n个方块,有四种操作: .move a onto b,把a和b上面的方块都放回原来位置,然后把a放到b上面: .move a over b,把a上面的放回原处,然后把a放在b所在的方块堆的上 ...