不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator 方式,如果并发操作,需要对 Iterator 对象加锁
不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator 方式,如果并发操作,需要对 Iterator 对象加锁。
正例: 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);
}
}
说明:以上代码的执行结果肯定会出乎大家的意料,那么试一下把“1”换成“2”,会是同样的 结果吗?
根本原因在于expectedModCount与modCount他们的不相等,由于执行了ArrayList中的remove(),modCount在每一次循环值会发生改变,而expectedModCount并没有发生,在执行checkForComodification()方法就会抛出异常。
如下代码:
编译器编译后的代码如下:
}
首先大家应该了解,对集合做remove,and等操作会触修改次数(modCount)的增加。
以下是集合实现的Iterator.hasNext()方法
cursor:下一个元素的索引位置(调用Interator.next()是会触发cursor+1)
size:集合长度
总结:如果我们我们用foreach删除的元素刚好是最后一个,删除完成前cursor刚好等于size的大小。但是,删除完成后size的数量减1,但是cursor并没有变化。导致下一次循环不相等继续向下执行,导致检查数组不通过,抛出java.util.ConcurrentModificationException
为什么使用下面的方法就不会出现这种情况:
请看箭头所指处:
foreach是直接调用集合的删除方法,而上面是调用iterator的删除方法:
相信大家一看便知!
1.首先检查集合
2.删除元素
3.cursor重新赋值
4.检查集合参数重新赋值
---------------------
作者:这个人好帅
来源:CSDN
原文:https://blog.csdn.net/weixin_39032575/article/details/80724984
版权声明:本文为博主原创文章,转载请附上博文链接!
不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator 方式,如果并发操作,需要对 Iterator 对象加锁的更多相关文章
- foreach循环里不能remove/add元素的原理
foreach循环 foreach循环(Foreach loop)是计算机编程语言中的一种控制流程语句,通常用来循环遍历数组或集合中的元素.Java语言从JDK 1.5.0开始引入forea ...
- 为什么阿里巴巴Java开发手册中强制要求不要在foreach循环里进行元素的remove和add操作?
在阅读<阿里巴巴Java开发手册>时,发现有一条关于在 foreach 循环里进行元素的 remove/add 操作的规约,具体内容如下: 错误演示 我们首先在 IDEA 中编写一个在 f ...
- 为什么阿里巴巴禁止在 foreach 循环里进行元素的 remove/add 操作--java.util.ConcurrentModificationException
摘要 foreach循环(Foreach loop)是计算机编程语言中的一种控制流程语句,通常用来循环遍历数组或集合中的元素. 在阿里巴巴Java开发手册中,有这样一条规定: 但是手册中并没有给出具体 ...
- 为什么禁止在 foreach 循环里进行元素的 remove/add 操作
首先看下边一个例子,展示了正确的做法和错误的错发: 这是为什么呢,具体原因下面进行详细说明: 1.foreach循环(Foreach loop)是计算机编程语言中的一种控制流程语句,通常用来循环遍历数 ...
- 有关集合的foreach循环里的add/remove
转自:Hollis(微信号:hollischuang) 在阿里巴巴Java开发手册中,有这样一条规定: 但是手册中并没有给出具体原因,本文就来深入分析一下该规定背后的思考. 1 .foreach循环 ...
- JSTL中c:forEach循环里的值的substr操作及对String操作的常用API
<c:forEach items="${dataList}" var="item" varStatus="itemStatus"> ...
- IT兄弟连 Java语法教程 数组 使用foreach循环遍历数组元素
从JDK5之后,Java提供了一种更简单的循环:foreach循环,也叫作增强for循环,这种循环遍历数组和集合更加简洁.使用foreach循环遍历数组和集合元素时,无需获得数组或集合的长度,无需根据 ...
- 禁止foreach循环使用remove/add----快速失败
阿里巴巴开发手册中有一条: 7[强制]不要在 foreach 循环里进行元素的 remove / add 操作. remove 元素请使用 Iterator 方式,如果并发操作,需要对 Iterato ...
- [置顶] java的foreach循环
foreach语句是java5之后的新特征之一,在循环遍历数组.集合方面更加简洁. 使用foreach循环遍历数组和集合时,无需获得数组和集合的长度,无须根据索引来访问数组元素和集合元素,foreac ...
随机推荐
- 卡在checking installable status
npm install卡在checking installable status 笔者在使用NPM过程中经常会用到npm install命令,发现有时候会卡在checking installable ...
- Ubuntu下无法输入中文问题解决
首先是要安装了中文输入法,下面以搜狗为例. 从system settings 进入language support ,在keyboard input method system 中是看不到自己安装的搜 ...
- BZOJ2512 : Groc
最优解一定是将起点.终点以及所有必经点连接成一棵树,对于每条树边恰好走两次,而从起点到终点的一条路径只走一次. 考虑连通性DP,设$f[i][j][k][x]$表示考虑完前$i$个走道,第$i$个走道 ...
- BZOJ4910 : [Sdoi2017] 苹果树
问题等价于树形依赖背包,允许一条链每个点各免费一次. 设$f[i][j]$表示按DFS序考虑到$i$,体积为$j$的最大收益. 先放入不能免费的物品,等遍历完儿子后再放入必选的物品,那么$i$到根路径 ...
- BZOJ4223 : Tourists
将位置划分成$O(m)$段区间,每段最早被阻挡的时间可以用堆维护. 那么每段区间对询问的贡献独立,扫描线处理即可. 时间复杂度$O(m\log m)$. #include<cstdio> ...
- shell脚本使用技巧4--读取字符,重复执行
ls | cat -n > out.txt 给输出的信息加行号并导出到out.txt 利用shell生成一个独立的进程 pwd; (cd /bin; ls); pwd; 开启一个子shell,不 ...
- yii2 getter
GridView 表格多余内容显示 ... 1.直接在 GridView 中使用匿名函数书写,这种适合单个使用 <?= GridView::widget([ 'dataProvider' =&g ...
- PAT基础6-9
6-9 统计个位数字 (15 分) 本题要求实现一个函数,可统计任一整数中某个位数出现的次数.例如-21252中,2出现了3次,则该函数应该返回3. 函数接口定义: int Count_Digit ( ...
- 【C语言程序】让用户输入一句话,输出这句话中每个单词含有多少个字母
#include <stdio.h> #define N 100 //宏定义,用N表示100 int main(int argc, char *argv[]) { ; char s ...
- web建包创建类
1.创建一个人类名