ArrayList之坑点
ConcurrentModificationException异常
详细原因参见 http://www.cnblogs.com/dolphin0520/p/3933551.html
缘起iterator
简单来说:在iterator中遍历以及删除时都会去执行如下检查
final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException();}
modCount 就是modify count 对队列修改的次数。
那么expectedModCount是什么时候赋予的呢?
public Iterator<E> iterator() {return new Itr();}private class Itr implements Iterator<E> {int cursor; // index of next element to returnint lastRet = -1; // index of last element returned; -1 if no suchint expectedModCount = modCount;
在Iterator对象初始化的时候就赋予了当前的modCount值,如果这之后在执行iterator.next() 的同时,还去调用list.add或remove操作,那么肯定会出现expectedModCount != modCount的情况,从而导致异常产生。
仅仅只是iterator?牵出foreach
被广泛使用的foreach,其实间接的就是使用iterator实现的。(在JDK中没法看到具体实现,反编译可以看到字节码窥探到) 参见 http://blog.csdn.net/a596620989/article/details/6930479
为什么作者要这么做呢?
在遍历的时候他不希望队列在别的线程里还进行队列的修改,也就是说在设计的时候没有考虑多线程同步问题,然后用这种条件来限制。
该如何解决
很弱的办法
在删除的时候使用iterator的remove ,因为他进行删除的时候,会同步一下modCount的值给expectedModCount。
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();}}
这个只能说解决了一小部分问题。遇到多线程还是有问题。
最后有2种解决办法:
1)在使用iterator迭代的时候使用synchronized或者Lock进行同步;
用这种同步锁的方式来阻止modCount不一致的情况发生。这个办法直接,但是需要自己手动添加锁。
2)使用并发容器CopyOnWriteArrayList代替ArrayList和Vector。见http://blog.csdn.net/xude1985/article/details/51418558
addAll
public boolean addAll(Collection<? extends E> c) {Object[] a = c.toArray();int numNew = a.length;ensureCapacityInternal(size + numNew); // Increments modCountSystem.arraycopy(a, 0, elementData, size, numNew);size += numNew;return numNew != 0;}
虽然我们看到有arraycopy,但是他复制的只是对象引用,而作为被指向的目标:对象数据则是没有任何改变。addAll只是浅拷贝而已,并没有进行深拷贝,所以你在改变对象内部数据的时候,仍旧是一变都变的
add
public boolean add(E e) {ensureCapacityInternal(size + 1); // Increments modCount!!elementData[size++] = e;return true;}
add时候并没有给你进行去重,所以你需要在调用add前自己去重
ArrayList之坑点相关推荐
- 常见的集合容器应当避免的坑
点击上方"方志朋",选择"置顶公众号" 技术文章第一时间送达! 本文经授权转载自微信公众号:crossoverJie 前言 前不久帮同事一起 review 一个 ...
- 使用了eclipse10年之后,我终于投向了IDEA
作者: 噢咦嗒的博客 链接:https://www.cnblogs.com/ouyida3/(点击阅读原文前去围观) 最近,改用了idea,同事都说我投敌了.当然,这些同事都是和我一样的"老 ...
- Java中ArrayList remove会遇到的坑
前言 平时最常用的莫过于ArrayList和HashMap了,面试的时候也是问答的常客.先不去管容量.负载因子什么的,就是简单的使用也会遇到坑. Remove 元素 经常遇到的一个场景是:遍历list ...
- java arraylist 初始化_一不小心就让Java开发踩坑的fail-fast是个什么鬼?
什么是fail-fast 首先我们看下维基百科中关于fail-fast的解释: In systems design, a fail-fast system is one which immediate ...
- 使用Arrays.asList、ArrayList的subList时,你有踩过这些坑吗?
前沿技术早知道,弯道超车有希望 积累超车资本,从关注DD开始 作者:申城异乡人, 图文编辑:xj 来源:https://blog.csdn.net/zwwhnly/article/details/10 ...
- 从源码角度解析ArrayList.subList的几个坑
前言 <阿里巴巴Java开发手册>中提出了以下几点建议和规则: 「规则1:」 「规则2:」本文通过源码分析,给大家讲清楚<手册>为什么这么规定 ArrayList的subLis ...
- ArrayList分页Lists.partition遇到的坑
一.问题的发现 最近在用分布式任务powerjob的时候,发现了一个关于数组分页之后的序列化问题.事情是这样的,在我执行MapReduce模式的时候,发现了在生成子任务时报了com.esoterics ...
- ArrayList 源码坑读学习记录
Field DEFAULT_CAPACITY 这个属性是ArrayList的容量,默认初始就赋值位10,如果构造函数没有出入集合容量的话,就会用这个默认的初始化容量 private static fi ...
- ArrayList转Json的2个坑
库你急哇,哈集美马戏特~~ 1.使用类名作为参数时 public static List load(String fileName, Class entityClass) 要是直接将entityCla ...
最新文章
- 对于未来的多种可能,这几位中国科学家想说
- dump mysql_mysql/mariadb知识点总结(28):mysql备份工具之mysqldump
- 无法加载主类的10中方法
- 【Java】利用for循环打印心型
- 消息中间件kafka概述和安装
- Centos7.3 坑爹网络配置
- Leetcode每日一题:463.island-perimeter(岛屿的周长)
- 1.VBA实现EXCEL中Sheet1的 甲列 相同数值的行对应的乙列的数的和作为Sheet2中丙列中与Sheet1中甲列 相同的行对应的丁列的值...
- javascript教程现有Web App模式的问题以及挑战
- android打电话录音软件,Android uni-app实现音视频通话
- 【我的OpenGL学习进阶之旅】如何抽取着色器代码到assets目录下的GLSL文件,以及如何通过Java或者C++代码来加载着GLSL文件?
- C语言中标量变量,如何从标量变量A,B,C和D中产生总线BusQ[0:3]?如何从两条总线B usA[0:3]和BusY[20:15]形成新的总线BusR[10:1...
- meta的http-equiv属性
- 计算机视觉 — Harris角点检测
- 关于概率论和模糊数学的区别
- 喝酒娱乐小游戏助力神器微信小程序源码下载多种游戏选择玩法多种
- ad批量走线_AD中 蛇形走法、多条网络同时布线、交互布线、logo、差分走线、3D...
- pc 微信小程序 位置
- 一种高性能无锁队列设计
- 使用 Apache ECharts 实现圣都装饰的延期日历图