Java_foreach不能remove
foreach
阿里巴巴java开发手册
【强制】不要在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。
反例
List<String> a = new ArrayList<String>();
a.add("1");
a.add("2");
for (String temp : a) {
if("1".equals(temp)){
a.remove(temp);
}
}
正例
Iterator<String> it= a.iterator();
while(it.hasNext()){
String temp = it.next();
if(删除元素的条件){
it.remove();
}
}
foreach源码
foreach遍历集合,其实是走的Iterator,首先判断hasNext(),如果没有了则终止循环,否则next()获取元素时,next()时,都要check一下集合元素个数是否变化了,如果变化了,则抛出异常。
Itr是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;
public boolean hasNext() {
return cursor != size;//游标不等于元素个数就是还有下一个
}
public E next() {
checkForComodification();//check是否并发修改
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];
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
modCount是集合添加元素、删除元素的次数,expectedModCount是预期的修改次数。增删操作会使得modCount+1,不等于expetedModCount,所以抛出异常。
没有使用list.iterator时调用的是ArrayList自己的remove,并不会同步这两个值,导致抛出异常。调用了ArrayList.iterator之后,然后了Itr对象,此后再remove,remove方法中有让这两个值相等的操作。
迭代器方式移除
那为什么Iterator不会异常呢?
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();
}
}
迭代器的remove方法会修改expectedModCount,从而使modCount与之相等
参考:https://blog.csdn.net/wangjun5159/article/details/61415358
Java_foreach不能remove的更多相关文章
- EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...
- [LeetCode] Remove K Digits 去掉K位数字
Given a non-negative integer num represented as a string, remove k digits from the number so that th ...
- [LeetCode] Remove Duplicate Letters 移除重复字母
Given a string which contains only lowercase letters, remove duplicate letters so that every letter ...
- [LeetCode] Remove Invalid Parentheses 移除非法括号
Remove the minimum number of invalid parentheses in order to make the input string valid. Return all ...
- [LeetCode] Remove Linked List Elements 移除链表元素
Remove all elements from a linked list of integers that have value val. Example Given: 1 --> 2 -- ...
- [LeetCode] Remove Duplicates from Sorted List 移除有序链表中的重复项
Given a sorted linked list, delete all duplicates such that each element appear only once. For examp ...
- [LeetCode] Remove Duplicates from Sorted List II 移除有序链表中的重复项之二
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numb ...
- [LeetCode] Remove Duplicates from Sorted Array II 有序数组中去除重复项之二
Follow up for "Remove Duplicates":What if duplicates are allowed at most twice? For exampl ...
- [LeetCode] Remove Element 移除元素
Given an array and a value, remove all instances of that value in place and return the new length. T ...
随机推荐
- 微信小程序使用pako.js的踩坑笔记
问题 今天组长跟我们讨论了个问题,说是文章存储占用有点大,消耗宽带流量费,让我看看能不能找个方法解决一下(文章存储的是html字符串).第一反应是没什么头绪,能想到的就是将相同的字符串替换成一个标识之 ...
- ASP.NET Core 选项模式源码学习Options IOptionsMonitor(三)
前言 IOptionsMonitor 是一种单一示例服务,可随时检索当前选项值,这在单一实例依赖项中尤其有用.IOptionsMonitor用于检索选项并管理TOption实例的选项通知, IOpti ...
- Bean 字段复制利器 MapStruct
本文聊一个工具类,MapStruct ,它是一个在 dto,po(do/entity),vo 等这些 pojo 中转换字段的一个工具,在应用中经常有这样的转换,在 spring 和 apache-co ...
- 使用java语言实现八皇后问题
八皇后问题,在一个8X8的棋盘中,放置八个棋子,每个棋子的上下左右,左上左下,右上右下方向上不得有其他棋子.正确答案为92中,接下来用java语言实现. 解: package eightQuen; / ...
- 【前端知乎系列】ArrayBuffer 和 Blob 对象
本文首发在 个人博客 更多丰富的前端学习资料,可以查看我的 Github: <Leo-JavaScript>,内容涵盖数据结构与算法.HTTP.Hybrid.面试题.React.Angul ...
- 文件(图片)转base64
普通图片转base64 function getBase64(url, callback){ var canvas = document.createElement('canvas'),//创建can ...
- JS内置对象Array之reduce()用法
一.语法 arr.reduce(function(prev,cur,index,arr){ ... }, init); 其中, arr 表示原数组: prev 表示上一次调用回调时的返回值,或者初始值 ...
- eclipse新建maven项目报错Could not resolve arachetype org.apache.maven.archetypes:mmaven-archetype-quickstart:1.1 from any of the configured repositories
使用eclipse新建maven项目,按下图所示选择后,报错 报错截图 报错详细信息 Could not resolve archetype org.apache.maven.archetypes:m ...
- django基础之day05,F与Q查询,Q查询的高级用法
#F与Q查询 #*************************** F 查询 ******************** # F 查询数据库中的其他字段!!! #1.查询库存数大于卖出数的书籍 fr ...
- Object类和异常
Object类(所有类的顶级父类) 今天说的两个方法: equals: 用于比较两个对象是否相同,它其实是使用两个对象的内存地址进行比较,底层默认使用的是==比较运算符来判断的. ...