list set集合remove() ConcurrentModificationException 原因
来源:互联网 发布:php 5.4.10.tar.gz 编辑:程序博客网 时间:2024/06/06 20:58
方法一、
ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("two");
list.add("two");
list.add("two");
for(int i=0;i<list.size();i++){
if(list.get(i).equals("two")){
list.remove(i);
}
}
System.out.println(list);
执行结果
[one, two, two]
注意: 此种方法可以删除list的数据,但删除后list的数据会自动向前面移动,这样会导致执行的结果和想要达到的效果不一样。
方法二、
ArrayList<String> list2 = new ArrayList<String>();
list2.add("one");
list2.add("two");
list2.add("two");
list2.add("two");
list2.add("two");
for(String s:list2){
if(s.equals("two")){
list2.remove(s);
}
}
System.out.println(list2);
执行结果
Exception in thread "main" java.util.ConcurrentModificationException at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372) at java.util.AbstractList$Itr.next(AbstractList.java:343) at com.learn.jdk16.util.ConcurrentModification.main(ConcurrentModification.java:40)
ArrayList<String> list3 = new ArrayList<String>();
list3.add("one");
list3.add("two");
list3.add("two");
list3.add("two");
list3.add("two");
Iterator<String> iter = list3.iterator();
while(iter.hasNext()){
String s = iter.next();
if(s.equals("two")){
iter.remove();
}
}
System.out.println(list3);
执行结果
[one]
删除还是用迭代器的比较好,其它的都会有问题.
----------------------------------------------------------
对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 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。
所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性
所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性
0 0
- list set集合remove() ConcurrentModificationException 原因
- List remove时出错"ConcurrentModificationException"
- 从ConcurrentModificationException到 list remove
- List集合中list.remove()返回false原因
- list执行remove和add方法时,报java.util.ConcurrentModificationException的原因
- java.util.ConcurrentModificationException 集合remove异常
- Set集合、list集合
- Java 集合 ConcurrentModificationException异常原因和解决方法
- List集合 remove
- List 集合remove问题
- list add set remove方法
- 集合List,Set
- 集合 list set
- 集合,list,set,map
- List Set 集合概述
- List、Set、Map集合
- List、Set、Map集合
- 集合list,set,map
- [leetcode: Python] 118.Pascal's Triangle
- listctrl第一列加图标的问题
- Unity 对象池(Object Pooling)理解与简单应用
- Lua内容关于for循环的总结(一)
- Hadoop2.7.3+Spark2.1.0完全分布式集群搭建过程
- list set集合remove() ConcurrentModificationException 原因
- 每周荐书:机器学习、spring MVC、Android(评论送书)
- 高并发rpc时如何connect(非阻塞)
- vue-cli 去掉严格模式
- Android APK Signature Scheme v2
- SNMPWALK,返回1.3.6.1.6.3
- px与em
- 贪心算法基础之最小生成树 51nod Kruskal算法
- 排序算法--冒泡排序