Iterator迭代器解决[为何禁止在foreach内增删]
迭代器的应用场景:
1、对集合进行增加删除,禁止使用foreach,循环的动态操作
2、倒序遍历
3、遍历循环
步入正题:为何禁止在foreach内进行增删?
先看一下代码:
/**
* 正例:
* Iterator<String> iterator = list.iterator();
* while (iterator.hasNext()) {
* String item = iterator.next();
* if (删除元素的条件) {
* iterator.remove();
* }
* }
* 反例:
* List<String> list = new ArrayList<String>();
* list.add("1");
* list.add("2");
* for (String item : list) {
* if ("1".equals(item)) {
* list.remove(item);
* }
* }
*/
这段代码是,在阿里的开发手册中的一段代码。
我们先看下面场景:
/**
* 场景一:对集合进行删除,增加、for循环
* 错误:这里会报出数据越界异常,
* 因为:remove掉一个元素后,整个长度发生变化,所以发生异常
* 改进:采用forList.size()动态
*/
List<String> forList = new ArrayList<>();
forList.add("a");
forList.add("b");
forList.add("c");
int length = forList.size();
for (int i = 0; i < length; i++) {
if ("a".equals(forList.get(i))) {
forList.remove(i);
}
}
System.out.println(forList);
/**
* 产生新问题:
* 错误:运行便会发现:将b移除不完整,
* 因为:删除后整个游标向下,数组向上,刚好空出1个位置,
* 紧接着的第二位没有进行比对,所以产生问题
* 解决:数据长度减一与游标保持统一
*/
List<String> forList1 = new ArrayList<>();
forList1.add("a");
forList1.add("b");
forList1.add("b");
forList1.add("c");
for (int i = 0; i < forList1.size(); i++) {
if ("b".equals(forList1.get(i))) {
forList1.remove(i);
i--;
}
}
System.out.println(forList1);
通过上个场景,知道在for循环内,为啥不建议用remove/add
在foreach循环内,再接着看下面这个场景?
/**
* 场景二:
* foreach循环,的remove/add操作
*/
List<String> forEach = new ArrayList<>();
forEach.add("a");
forEach.add("b");
forEach.add("c");
for (String each : forEach) {
if ("a".equals(each)) {
forEach.remove(each);
}
}
/**
* 产生的异常:
* Exception in thread "main" java.util.ConcurrentModificationException
* at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
* at java.util.ArrayList$Itr.next(ArrayList.java:859)
*/
/**
* 源码:Itr实现了Iterator接口(删减部分)
* private class Itr implements Iterator<E> {
* @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();
* }
*
* 如果有更改则抛出ConcurrentModificationException异常,
*
* final void checkForComodification() {
* 之前的版本不等于,当前的版本,判断为数据更新了。
* 那么?为什么产生这样的判断呢,因为你删除后变为新数组,来不及
* 更新版本,jvm不知道你当前数据状态,是否变化,无法再进行遍历
* if (modCount != expectedModCount)
* throw new ConcurrentModificationException();
* }
* }
*/
/**
* 改进:
*
*/
List<String> forEachIterator = new ArrayList<>();
forEachIterator.add("a");
forEachIterator.add("b");
forEachIterator.add("c");
java.util.Iterator<String> iterator = forEachIterator.iterator();
while (iterator.hasNext()) {
String next = iterator.next();
if ("a".equals(next)) {
iterator.remove();
}
}
这里:foreach实现的就是迭代器。
补充:倒序循环
/**
* 场景三:
* 应用:倒序遍历
*/
List<String> forEachIteratorDown = new ArrayList<>();
forEachIteratorDown.add("a");
forEachIteratorDown.add("b");
forEachIteratorDown.add("c");
ListIterator<String> item = forEachIteratorDown.listIterator();
//这里需要先将指针移向最后一位,再进行倒叙
while (item.hasNext()) {
item.next();
}
while (item.hasPrevious()) {
String previous = item.previous();
System.out.println(previous);
}
更多技术资讯可关注:itheimaGZ获取
Iterator迭代器解决[为何禁止在foreach内增删]的更多相关文章
- [设计模式] Iterator - 迭代器模式:由一份奥利奥早餐联想到的设计模式
Iterator - 迭代器模式 目录 前言 回顾 UML 类图 代码分析 抽象的 UML 类图 思考 前言 这是一包奥利奥(数组),里面藏了很多块奥利奥饼干(数组中的元素),我将它们放在一个碟子上慢 ...
- 为什么阿里巴巴禁止在 foreach 循环里进行元素的 remove/add 操作--java.util.ConcurrentModificationException
摘要 foreach循环(Foreach loop)是计算机编程语言中的一种控制流程语句,通常用来循环遍历数组或集合中的元素. 在阿里巴巴Java开发手册中,有这样一条规定: 但是手册中并没有给出具体 ...
- [C# 设计模式] Iterator - 迭代器模式:我与一份奥利奥早餐的故事
Iterator - 迭代器模式 目录 前言 回顾 UML 类图 代码分析 抽象的 UML 类图 思考 前言 这是一包奥利奥(数组),里面藏了很多块奥利奥饼干(数组中的元素),我将它们放在一个碟子上慢 ...
- C#:iterator 迭代器/partial class 分布类/泛型
C#:iterator 迭代器/partial class 分布类/泛型 iterator 迭代器 写个最简单的迭代,(迭代一个字符串数组): 1.实现接口中的方法: 1 using System; ...
- ES6笔记(6)-- Set、Map结构和Iterator迭代器
系列文章 -- ES6笔记系列 搞ES6的人也是够无聊,把JS弄得越来越像Java.C++,连Iterator迭代器.Set集合.Map结构都出来了,不知道说什么好... 一.简单使用 1. iter ...
- 设计模式(十五):Iterator迭代器模式 -- 行为型模式
1.概述 类中的面向对象编程封装应用逻辑.类,就是实例化的对象,每个单独的对象都有一个特定的身份和状态.单独的对象是一种组织代码的有用方法,但通常你会处理一组对象或者集合. 集合不一定是均一的.图形用 ...
- STL之iterator(迭代器)
3.迭代器简单介绍 除了使用下标来訪问vector对象的元素外,标准库还提供了訪问元素的方法:使用迭代器.迭代器是一种检查容器内元素而且遍历元素的数据类型. 百科释义: 迭代器(iterator)是一 ...
- Python 中 Iterator(迭代器)和Iterable(迭代对象)的区别
直接可以用作for循环的数据类型有以下几种: tuple.list.dict.str等, 上述数据类型可以用作for循环的叫做可迭代对象Iterable.可以使用isinstance判断一个对象是否是 ...
- 增强for、iterator迭代器
因为初学java,对部分语法还模棱两可, 在做练习的时候,用增强for遍历字符串编译报错 所以来复习下增强for原理和适用范围 一.增强for概念 增强for(也成为for each循环)是JDK 1 ...
随机推荐
- (转)ERROR : The processing instruction target matching "[xX][mM][lL]" is not allowed.
现象:ERROR : The processing instruction target matching "[xX][mM][lL]" is not allowed. 异常解 ...
- 吴裕雄--天生自然 JAVASCRIPT开发学习:Math(算数) 对象
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- Codeforces Round #619 (Div. 2)E思维+二维RMQ
题:https://codeforces.com/contest/1301/problem/E 题意:给个n*m的图形,q个询问,每次询问问询问区间最大的合法logo的面积是多少 分析:由于logo是 ...
- Django1.11基础视图
Django视图 路由命名与reverse反解析 在项目urls中的include函数,使用namespace参数定义路由命名空间 url(r'^',incude('book.urls',namesp ...
- Halcon函数总结(一)
Halcon函数总结: read_image( :Image :FileName : ) //读入图像 crop_part(Image : ImagePart :Row,Column,Width,H ...
- 从定时器的选型,到透过源码看XXL-Job(下)
透过源码看xxl-job (注:本文基于xxl-job最新版v2.0.2, quartz版本为 v2.3.1. 以下提到的调度中心均指xxl-job-admin项目) 上回说到,xxl-job是一个中 ...
- Docker部署zookeeper集群和kafka集群,实现互联
本文介绍在单机上通过docker部署zookeeper集群和kafka集群的可操作方案. 0.准备工作 创建zk目录,在该目录下创建生成zookeeper集群和kafka集群的yml文件,以及用于在该 ...
- Tomcat启动报内存溢出错误:java.lang.OutOfMemoryError: PermGen space
windows操作系统 找到D:\Tomcat-7\apache-tomcat-7.0.28\bin(解压安装的Tomcat)目录下的catalina.bat文件,打开该文件,找到下图所示的内容:添加 ...
- openlayers的loaders方式加载
openlayers loaders方式加载 let layerVector = new ol.layer.Vector({ source : new ol.source.Vector({ loade ...
- vue-router HTML5 History 模式(转自官网)
vue-router 默认 hash 模式 -- 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载. 如果不想要很丑的 hash,我们可以用路由的 his ...