在做项目中用到List存储数据,在里面做数据操作时候用到了删除。结果抛出ConcurrentModificationException异常。在这里把问题总结一下。

原因:

ArrayList进行foreach时所调用的迭代器(内部迭代器Itr)
/**
* An optimized version of AbstractList.Itr
*/
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
// expectedModCount是Itr特有的,modCount是公共的
// expectedModCount和modCount默认是两者相等的;ArrayList进行删除修改都会更新modCount的值
// 当ArrayList通过foreach进入它的内部迭代器Itr时,expectedModCount就被赋值为modCount的值,后续ArrayList进行增加或删除,只会更新modCount,而不会同步更新expectedModCount
// 所以迭代器根据这两个值进行判断是否有并发性修改
int expectedModCount = modCount;
 
public boolean hasNext() {
return cursor != size;
}
// ArrayList通过foreach(即增强for循环)来循环是调用的是ArrayList中内部类Itr的next()
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
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];
}
// ArrayList中迭代器删除方法
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
 
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
// 通过ArrayList中foreach(即通过ArrayList内部Itr的迭代器)进行删除元素
// 此时会进行赋值 expectedModCount = modCount;而不会抛出异常
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
ArrayList通过foreach迭代是调用的其内部类Itr的next方法。如果通过foreach循环,要去除某些元素,只能通过迭代器删除。因为迭代器删除后会对expectedModCount = modCount设置,不会再循环过程因为expectedModCount 和 modCount值不相等而抛出异常了。如果是通过ArrayList的删除则只会对modCount进行更新,但是ArrayList内部迭代器Itr的属性expectedModCount却没有得到更新,所以抛异常。
 
解决: List.iterator() 直接用迭代器去迭代,然后去删除元素。
 

ArrayList删除--------ConcurrentModificationException问题的更多相关文章

  1. ArrayList的ConcurrentModificationException异常和多线程下的异常

    一.ConcurrentModificationException ArrayList源码看为什么出现异常: public class ArrayList<e> extends Abstr ...

  2. ArrayList中ConcurrentModificationException

    java中两种基本的集合结构ArrayList和LinkedList底层有两种不同的存储方式实现,ArrayList为数组实现,属于顺序存储,LinkedList为链表实现,属于链式存储,在对Arra ...

  3. Android 两个ArrayList找出相同元素及单个ArrayList删除元素

    //从一个ArrayList中删除重复元素 List<String> arrayList1 = new ArrayList<String>(); arrayList1.add( ...

  4. ArrayList删除特定元素的方法

    最朴实的方法,使用下标的方式: ArrayList<String> al = new ArrayList<String>(); al.add("a"); a ...

  5. ArrayList在foreach正常迭代删除不报错的原因

    一.背景 在以前的随笔中说道过ArrayList的foreach迭代删除的问题:ArrayList迭代过程删除问题 按照以前的说法,在ArrayList中通过foreach迭代删除会抛异常:java. ...

  6. ArrayList的删除姿势你都知道了吗

    引言 前几天有个读者由于看了<ArrayList哪种遍历效率最好,你真的弄明白了吗?>问了个问题普通for循环ArrayList为什么不能删除连续重复的两个元素?其实这个描述是不正确的.正 ...

  7. jdk源码分析之ArrayList

    ArrayList关键属性分析 ArrayList采用Object数组来存储数据 /** * The array buffer into which the elements of the Array ...

  8. subList ArrayList LinkedList

    List<E> subList(int fromIndex,int toIndex) 该方法返回原有集合从fromIndex 到 toIndex之间一部分数据,组成一个新的集合,这两个集合 ...

  9. 死磕 java集合之ArrayList源码分析

    欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. 简介 ArrayList是一种以数组实现的List,与数组相比,它具有动态扩展的能力,因此也可 ...

随机推荐

  1. Tomcat启动报错:Possible root causes include a too low setting for -Xss and illegal cyclic inheritance dependencies

    错误代码如下: Caused by: java.lang.IllegalStateException: Unable to complete the scan for annotations for ...

  2. jsfiddle修改个人头像

    找了半天终于知道修改jsfiddle头像的方法了~ JsFiddle将Gravatar - 全球认可的头像用于个人资料图片.必须在这里改变你的头像,它也会在jsFiddle中自动更新. 注意,两者的注 ...

  3. python-路径处理path

    #-*- coding:utf-8 -*- # file: class_01_path.py #本次学习:OS模块--处理路径 #F:\pythonzhm\study_181112 import os ...

  4. .NET C#获取当前网页地址

    摘自:https://www.cnblogs.com/vichin/p/6004249.html 设当前页完整地址是:http://www.jb51.net/aaa/bbb.aspx?id=5& ...

  5. (转)日期类型的input元素设置默认值为当天

    原文地址 html5的form元素对日期时间有丰富的支持 <input type="date"> <input type="time"> ...

  6. Ruby学习笔记3:Rendering(渲染)和 Redirect(重定向)

    1. Rendering Rendering 是特别要告诉Controller 中的methods,要哪个view file来显示给用户.We can show Views as we wish! E ...

  7. 【转】AD常用端口

    通常在域环境中我们有部分设备在DMZ区时,就需要知道AD的相关端口.在此提供给各位: 用户登录与验证身份时会用到的连接端口用户登录时会用到以下的服务,因此如果用户的计算机与域控制器之间被防火墙隔开,就 ...

  8. .Net Web下 Console输出

    .NET winform的时候,一直都是用 Console.Write向控制台输出信息的,但是在Web中是输出不了的. web程序执行时,是被附加到IIS进程的一个单独的AppDomain中的,所以就 ...

  9. leetcode295

    public class MedianFinder { List<int> list = null; ; /** initialize your data structure here. ...

  10. SecureCRT显示乱码的解决办法

    下面来看看SecureCRT的显示出现乱码这种情况.比如: 现在我们重新设置一下 设置下图中的配置 1.选择字符编码为UTF-8. 2.设置字符集为GB2312后保存好后确认退出. 3.再次测试一下.