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的更多相关文章

  1. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  2. [LeetCode] Remove K Digits 去掉K位数字

    Given a non-negative integer num represented as a string, remove k digits from the number so that th ...

  3. [LeetCode] Remove Duplicate Letters 移除重复字母

    Given a string which contains only lowercase letters, remove duplicate letters so that every letter ...

  4. [LeetCode] Remove Invalid Parentheses 移除非法括号

    Remove the minimum number of invalid parentheses in order to make the input string valid. Return all ...

  5. [LeetCode] Remove Linked List Elements 移除链表元素

    Remove all elements from a linked list of integers that have value val. Example Given: 1 --> 2 -- ...

  6. [LeetCode] Remove Duplicates from Sorted List 移除有序链表中的重复项

    Given a sorted linked list, delete all duplicates such that each element appear only once. For examp ...

  7. [LeetCode] Remove Duplicates from Sorted List II 移除有序链表中的重复项之二

    Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numb ...

  8. [LeetCode] Remove Duplicates from Sorted Array II 有序数组中去除重复项之二

    Follow up for "Remove Duplicates":What if duplicates are allowed at most twice? For exampl ...

  9. [LeetCode] Remove Element 移除元素

    Given an array and a value, remove all instances of that value in place and return the new length. T ...

随机推荐

  1. [TimLinux] 养成一个习惯

    1. 习惯 在博客园开博之前,大约六个月之前,我开始给自己定下坚持跑步的目标,从而养成了一个习惯.就在大约半个月前,回顾自己的工作经历的时候,发现还有一个来月自己就工作十年了,为此我树立了一个新的目标 ...

  2. Mysql双活方案

    #### 说明 Mysql主主互备即为两个mysql的互为备份机   ##### Windows下安装步骤(Linux下步骤类似,基本就是装上mysql,然后修改配置来完成主从的设置) - step1 ...

  3. Jquery判断当前时PC端,移动端,平板端屏幕

    $(function(){     // console.log(navigator.userAgent);     var os = function (){       var ua = navi ...

  4. 【算法】272-每周一练 之 数据结构与算法(Dictionary 和 HashTable)

    这是第五周的练习题,上周忘记发啦,这周是复习 Dictionary 和 HashTable. 下面是之前分享的链接: [算法]200-每周一练 之 数据结构与算法(Stack) [算法]213-每周一 ...

  5. Java并发编程杂记(1)

    高并发: cpu -- 缓存 -- 内存 资源利用率 公平性 便利性   生活举例 --- 串行任务中的异步性:我在烧水的时候看书 --- 平衡点   安全性问题 --- 产生竞态条件 共享数据 -- ...

  6. Nginx(四)-- Nginx的扩展-OpenRestry

    1. OpenResty 安装及使用 OpenResty 是一个通过 Lua 扩展 Nginx 实现的可伸缩的 Web 平台,内部集成了大量精良的 Lua 库.第三方模块以及大多数的依赖项.用于方便地 ...

  7. 后端程序猿标配之linux命令

    超清图片,可放大查看. 来源:https://www.cnblogs.com/ryanlamp/p/7511883.html

  8. Runtime - 关联对象使用方法及注意点

    大家都知道在分类里,可以间接的添加属性,运用runtime关联对象. 如下图,只是声明了btnClickedCount的set, get方法而已 并没有生成_btnClickedCount 成员变量, ...

  9. 在Linux系统下制作系统启动盘(Ubuntu Linux)

    在Linux系统下制作系统启动盘有两种方法: 1.用dd命令 2.用Linux自带的图形界面工具 Startup Disk Creator 本教程使用第2种方式,用Linux自带的图形界面工具制作系统 ...

  10. Web基础了解版05-Servlet

    Servlet Servlet? 从广义上来讲,Servlet规范是Sun公司制定的一套技术标准,包含与Web应用相关的一系列接口,是Web应用实现方式的宏观解决方案.而具体的Servlet容器负责提 ...