关于List的ConcurrentModificationException
对ArrayList的操作我们可以通过索引象来访问,也可以通过Iterator来访问,只要不对ArrayList结构上进行修改都不会造成ConcurrentModificationException,单独用索引对ArrayList进行修改也不会造成该问题,造成该问题主要是在索引和Iterator混用。可以通过JDK的源码来说明该问题。
首先看下AbstractList的Iterator内的代码:
- /**
- *在Iterator的内部有个expectedModCount 变量,
- *该变量每次初始化*Iterator的时候等于ArrayList的modCount,modCount记录了对ArrayList的结构修改次数,
- *在通过Iterator对ArrayList进行结构的修改的时候都会将expectedModCount 与modCount同步,
- *但是如果在通过Iterator访问的时候同时又通过索引的方式去修改ArrayList的结构的话,
- *由于通过索引的方式只会修改modCount不会同步修改expectedModCount 就会导致
- *modCount和expectedModCount 不相等就会抛ConcurrentModificationException,
- *这也就是Iterator的fail-fast,快速失效的。所以只要采取一种方式操作ArrayList就不会出问题,
- *当然ArrayList不是线程安全的,此处不讨论对线程问题。
- *
- */
- int expectedModCount = modCount;
- public E next() {
- checkForComodification();//判断modeCount与expectedModCount 是否相等,如果不相等就抛异常
- try {
- E next = get(cursor);
- lastRet = cursor++;
- return next;
- } catch (IndexOutOfBoundsException e) {
- checkForComodification();
- throw new NoSuchElementException();
- }
- }
- public void remove() {
- if (lastRet == -1)
- throw new IllegalStateException();
- checkForComodification();//同样去判断modeCount与expectedModCount 是否相等
- try {
- AbstractList.this.remove(lastRet);
- if (lastRet < cursor)
- cursor--;
- lastRet = -1;
- expectedModCount = modCount;//此处修改ArrayList的结构,所以要将expectedModCount 于modCount同步,主要是AbstractList.this.remove(lastRet);的remove方法中将modCount++了,导致了modCount与expectedModCount 不相等了。
- } catch (IndexOutOfBoundsException e) {
- throw new ConcurrentModificationException();
- }
- }
- //判断modCount 与expectedModCount是否相等,如果不相等就抛ConcurrentModificationException异常
- final void checkForComodification() {
- if (modCount != expectedModCount)
- throw new ConcurrentModificationException();
- }
故我的结论是:对ArrayList的操作采用一种遍历方式,要么索引,要么Iterator别混用即可。
下面是网上看见别人的解释:写道
所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性
关于List的ConcurrentModificationException的更多相关文章
- java.util.ConcurrentModificationException 解决办法(转载)
今天在项目的中有一个需求,需要在一个Set类型的集合中删除满足条件的对象,这时想当然地想到直接调用Set的remove(Object o)方法将指定的对象删除即可,测试代码: public cla ...
- java.util.ConcurrentModificationException异常处理
ConcurrentModificationException异常处理 ConcurrentModificationException异常是Iterator遍历ArrayList或者HashMap数组 ...
- java.util.ConcurrentModificationException --map
key:3-key key:/v1.02-key Exception in thread "main" java.util.ConcurrentModificationExcept ...
- 偶遇到 java.util.ConcurrentModificationException 的异常
今天在调试程序 遇到了如此问题 贴上代码来看看稍后分析 List<String> list = null;boolean isUpdate = false;try { list = JSO ...
- 集合框架之——迭代器并发修改异常ConcurrentModificationException
问题: 我有一个集合,如下,请问,我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现. 使用普通迭代器出现的异常: ...
- 对ArrayList操作时报错java.util.ConcurrentModificationException null
用iterator遍历集合时要注意的地方:不可以对iterator相关的地方做添加或删除操作.否则会报java.util.ConcurrentModificationException 例如如下代码: ...
- Java ConcurrentModificationException异常原因和解决方法
Java ConcurrentModificationException异常原因和解决方法 在前面一篇文章中提到,对Vector.ArrayList在迭代的时候如果同时对其进行修改就会抛出java.u ...
- LinkedList - java.util.ConcurrentModificationException
package com.test.io; import java.io.BufferedReader; import java.io.FileNotFoundException; import jav ...
- java 多线程操作List,已经做了同步synchronized,还会有ConcurrentModificationException,知道为什么吗?
如题,最近项目里有个模块我做了异步处理方面的事情,在code过程中发现一个颠覆我对synchronized这个关键字和用法的地方,请问各位java开发者们是否对此有一个合理的解释,不多说,我直接贴出问 ...
随机推荐
- python调用py中rar的路径问题。
1.python调用py,在py中的os.getcwd()获取的不是py的路径,可以通过os.path.split(os.path.realpath(__file__))[0]来获取py的路径. 2. ...
- 在centos 服务器上安装phalcon框架 undefined symbol: php_pdo_get_dbh_ce
去git 下载对应版本的框架 命令行: sudo yum install php-devel pcre-devel gcc make 然后使用GIT clone到服务器上,然后 git clone g ...
- [deviceone开发]-心形点赞动画示例
一.简介 这个示例展示do_Animator组件的简单使用,通过点击"点赞"按钮,不断弹出心形图片,向上动画漂移到顶部消失.间隔时间和上下左右移动的步长都是一定范围的随机值.二.效 ...
- Android Weekly Notes Issue #223
Android Weekly Issue #223 September 18th, 2016 Android Weekly Issue #223 本期内容包括: Offline时间戳处理; Acces ...
- jQuery如何改变css伪元素样式
首先我们看一下css伪元素是什么: CSS 伪元素用于向某些选择器设置特殊效果. 伪元素有哪些: :first-line 伪元素:"first-line" 伪元素用于向文本的首行设 ...
- Java 反射 使用总结
转载请标明出处:http://www.cnblogs.com/zhaoyanjun/p/6074887.html1 本文出自[赵彦军的博客] 反射机制是什么 反射机制是在运行状态中,对于任意一个类,都 ...
- AngularJS API
AngularJS 全局 API 用于执行常见任务的 JavaScript 函数集合 angular.lowercase() 转换字符串为小写 angular.uppercase() 转换字符串为大写 ...
- Mac上安装MySQL记录
下载最新的MySQL社区版 官方下载地址:http://dev.mysql.com/downloads/mysql/ 为了安装更方便,建议下载dmg安装包. 最新的版本是5.7.9. 安装MySQL ...
- shell-script的简单举例
#!/bin/bash #defind the path PATH=/usr/local export PATH read -p "please input your first name: ...
- 轻量级C#编辑器RoslynPad
简介 RoslynPad是一个Apache 2.0协议开源的轻量级C#编辑器.支持自动完成,语法提示,修改建议等功能.很适合平时随手写个C#程序看看运行结果. 目前版本:0.10.1,无需保存也可以运 ...