Java:Iterator接口与fail-fast小记
Java:Iterator接口与fail-fast小记
对 Java 中的 Iterator接口 和 fail-fast,做一个微不足道的小小小小记
Iterator
Iterator接口
Iterator:迭代器
迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。
Java 中的 Iterator 功能比较简单,并且只能单向移动:
- 使用方法
public Iterator iterator()要求容器返回一个 Iterator。第一次调用 Iterator 的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被 Collection 继承。 - 使用
public E next()获得序列中的下一个元素。 - 使用
public boolean hasNext()检查序列中是否还有元素。 - 使用
default void remove()将迭代器新返回的元素删除。
进一步:
迭代:即 Collection 集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。
public class IteratorDemo {
public static void main(String[] args) {
// 使用多态方式 创建对象
Collection<String> coll = new ArrayList<String>();
// 添加元素到集合
coll.add("串串星人");
coll.add("吐槽星人");
coll.add("汪星人");
// 遍历
// 使用迭代器 遍历 每个集合对象都有自己的迭代器
Iterator<String> it = coll.iterator();
// 泛型指的是 迭代出 元素的数据类型
while(it.hasNext()){ //判断是否有迭代元素
String s = it.next();//获取迭代出的元素
System.out.println(s);
}
}
}
注:在进行集合元素取出时,如果集合中已经没有元素了,还继续使用迭代器的next方法,将会发生
java.util.NoSuchElementException没有集合元素的错误。
ListIterator
ListIterator 与 Iterator 的相同点:
都是迭代器,当需要对集合中元素进行遍历不需要干涉其遍历过程时,这两种迭代器都可以使用;
ListIterator 实现了 Iterator 接口;
public interface ListIterator<E> extends Iterator<E>
不同点:
- 使用范围不同:Iterator 可用来遍历 Set、List、Map集合,但是 ListIterator 只能用来遍历 List。
- Iterator 对集合只能是前向遍历(
hasNext(),Next()),ListIterator 既可以前向也可以后向(hasNext(),Next(),hasPrevious(),previous()); - ListIterator 可以定位当前索引的位置,
nextIndex()和previousIndex()可以实现。Iterator没有此功能。 - ListIterator 有 add 方法,可以向 List 中添加对象,而 Iterator 不能;
- 都可实现删除操作,但是 ListIterator 可以实现对象的修改,
set()方法可以实现。Iterator仅能遍历,不能修改
总之:ListIterator 实现了 Iterator 接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引等等。
Enumeration
与 Enumeration 相比,Iterator 更加安全,因为当一个集合正在被遍历的时候,它会阻止其它线程去修改集合。否则会抛出 ConcurrentModificationException 异常。这其实就是 fail-fast 机制。具体区别有三点:
- Iterator 的方法名比 Enumeration 更科学;
- Iterator 有 fail-fast 机制,比 Enumeration 更安全;
- Iterator 能够删除元素,Enumeration 并不能删除元素。
函数接口如下:
package java.util;
public interface Enumeration<E> {
boolean hasMoreElements();
E nextElement();
}
public interface Iterator<E> {
boolean hasNext();
E next();
void remove();
}
fail-fast
在上述 Iterator 中,介绍到 Enumeration 时,提到了 fail-fast 机制,在此做一点介绍
fail-fast 概述
fail-fast 的字面意思是“快速失败”。当我们在遍历集合元素的时候,经常会使用迭代器,但在迭代器遍历元素的过程中,如果集合的结构被改变的话,就会抛出异常,防止继续遍历。这就是所谓的快速失败机制。
fail-fast 迭代器抛出 ConcurrentModificationException,而 fail-safe 迭代器则不会。
结构上的改变:集合上的插入和删除就是结构上的改变;
对集合中某个元素进行修改的话,并不是结构上的改变;
抛出 ConcurrentModificationException 异常实例:
@Test
public void testFailFast(){
List<Integer> list = new ArrayList<>();
for(int i = 0; i < 20; i++){
list.add(i);
}
Iterator<Integer> it = list.iterator();
int temp = 0;
while(it.hasNext()){
if(temp == 3){
temp++;
list.remove(3); // 在迭代的过程中,改变了集合的结构,导致fail-fast
}else{
temp++;
System.out.println(it.next());
}
}
}
fail-fast 工作原理
public E next() {
checkForComodification();
...
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
当迭代器在执行 next() 方法时,会调用 checkForComodification(),当modCount != expectedModCount 时则抛出异常,而当集合的结构发生变化时,modCount 就会发生改变,如:
// ArrayList 在添加元素时,modCount就会被改变
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++; // 这里修改了!!!
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
fail-fast 的一些处理方法:
如果我们不希望在迭代器遍历的时候因为并发等原因,导致集合的结构被改变,进而可能抛出异常的话,我们可以在涉及到会影响到 modCount 值改变的地方,加上同步锁(synchronized),或者直接使用 Collections.synchronizedList 来解决。
fail-safe
java.util 包中的所有集合类都被设计为 fail-fast 的,而 java.util.concurrent 中的集合类都为 fail-safe 的。
对于采用 fail-safe 机制来说,当检测到正在遍历的集合的结构被改变时,不会抛出异常;
这是因为,当集合的结构被改变的时候,fail-safe 机制会在复制原集合的一份数据出来,然后在复制的那份数据遍历。
因此,虽然fail-safe不会抛出异常,但存在以下缺点:
- 复制时需要额外的空间和时间上的开销。
- 不能保证遍历的是最新内容。
参考:
https://mp.weixin.qq.com/s/q1r9Pno6ANUzZ9wMzA-JSg
https://blog.csdn.net/xiangyuenacha/article/details/84253630
https://www.jianshu.com/p/bee159e0bd49
Java:Iterator接口与fail-fast小记的更多相关文章
- java Iterator接口
Iterator主要遍历Collection集合中的元素,也有称为迭代器或迭代精灵. boolean hasNext():若被迭代的集合元素还没有被遍历,返回true. Object next(): ...
- Fail Fast and Fail Safe Iterators in Java
https://www.geeksforgeeks.org/fail-fast-fail-safe-iterators-java/ Fail Fast and Fail Safe Iterators ...
- java集合 之 Collection和Iterator接口
Collection是List,Queue和Set接口的父接口,该接口里定义的方法即可用于操作Set集合,也可以用于List和Queue集合.Collection接口里定义了如下操作元素的方法. bo ...
- Java API ——Collection集合类 & Iterator接口
对象数组举例: 学生类: package itcast01; /** * Created by gao on 15-12-9. */ public class Student { private St ...
- Java集合----概述、Collection接口、Iterator接口
Java 集合概述 Java 集合就像一种容器,可以把多个对象的引用放入容器中. Java 集合类可以用于存储数量不等的多个对象,还可用于保存具有映射关系的关联数组 Java 集合可分为 Set.Li ...
- Java容器深入浅出之Collection与Iterator接口
Java中用于保存对象的容器,除了数组,就是Collection和Map接口下的容器实现类了,包括用于迭代容器中对象的Iterator接口,构成了Java数据结构主体的集合体系.其中包括: 1. Co ...
- Java容器之Iterator接口
Iterator 接口: 1. 所有实现了Collection接口的容器类都有一个iterator方法用以返回一个实现了Iterator接口的对象. 2. Iterator 对象称作迭代器,用以方便的 ...
- java中的Iterator接口
Iterator接口 Iterator接口也是Java集合框架的成员,但它与Collection系列.Map系列的集合不一样:Collection系列集合.Map系列集合主要用于盛装其他对象,而Ite ...
- Java中的Enumeration、Iterable和Iterator接口详解
前言 在看各类Java书籍或者博文的时候,总是会遇到Enumeration.Iterable和Iterator这三个接口,如果对这几个接口不是很明白的话,总会让自己看着看着就迷惑了,正好这周末,抽空把 ...
随机推荐
- python3 爬虫五大模块之四:网页解析器
Python的爬虫框架主要可以分为以下五个部分: 爬虫调度器:用于各个模块之间的通信,可以理解为爬虫的入口与核心(main函数),爬虫的执行策略在此模块进行定义: URL管理器:负责URL的管理,包括 ...
- SpringSecurity-图解
- vue-admin-element 页面跳转
1.通过router-link 进行跳转 <router-link to="/china-quotation/business-function/quotation-request&q ...
- 【第二篇】- Git 安装配置之Spring Cloud直播商城 b2b2c电子商务技术总结
Git 安装配置 在使用Git前我们需要先安装 Git.Git 目前支持 Linux/Unix.Solaris.Mac和 Windows 平台上运行. Git 各平台安装包下载地址为:http://g ...
- 6步快速配置Tomcat环境变量(Win10)
一.配置 tomcat环境变量之前先安装jdk和配置jdk的环境变量 1.首先右击我的电脑(此电脑),点击属性,或者也可以从控制面板上打开,如下图,找到系统点击高级系统设置: 2.然后进入系统属性界面 ...
- 忘记root密码的情况下如何给指定账户开通远程访问
1.跳过验证使用root登录 net stop mysql //停止MYSQL服务 打开第一个cmd窗口,切换到mysql的bin目录,运行命令: mysqld --defaults-file=&qu ...
- JSON,XML设计模式详解
JSON在Java中的应用: Json概念: json 是一种轻量级的数据交换格式,采用完全独立于编程语言的文本格式用来存储和表示数据.JSON的语言简洁清晰,广为大众所欢迎,是一种理想的数据交换语言 ...
- jmeter 录制排除模式
jmeter录制时,静态的资源不需要,可以在录制的时候直接排除. .*\.(bmp|css|js|gif|icov|jpeg|png|swf|woff|woff2|htm|html).* .*\.(j ...
- python接口自动化--json解析神器jsonpath
前言 做接口测试的时候,大部分情况下返回的是json数据,我们需要对返回的json断言. 当返回的数据量比较大,并且嵌套的层级很深的时候,很多小伙伴不会取值,往往在返回结果取值上浪费很多时间.一直在寻 ...
- 安装SpaCy出现报错:requests.exceptions.ConnectionError: HTTPSConnectionPool(host='raw.githubusercontent.com', port=443):
内含安装步骤及报错解决:https://www.cnblogs.com/xiaolan-Lin/p/13286885.html