JAVA循环迭代中删除或添加集合数据报java.util.ConcurrentModificationException错误
1.写出下面的输出结果
public class test{
public static void main(String [] args)
List<String> list = new ArrayList<String>();
for (int i = 0; i < 10; i++) {
list.add(String.valueOf(i));
}
for(String s : list){
if(s.equals("3")){
list.remove(s);
}
}
System.out.println(list.size());
}
}
正确的输出:发生了并发的错误
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at test.main(test.java:35)
在这里for(String s : list){}的实质还是Iterator接口。
上面这段代码等价于下面:
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
String itString = (String)iterator.next();
if (itString.equals("3")) {
list.remove(itString); --这里会报错
//iterator.remove();---这里不会报错
}
}
所以我们来看看 list.iterator();的源码就知道为什么了
public Iterator<E> iterator() {
return new 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
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
@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];
}
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();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
从源码上我们可以看出,当我们调用next()方法的时候有一个检查modCount != expectedModCount;然后我们再来看看ArrayList的remove方法
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
}
从上面的代码中可以看出当我们进行remove的时候modeCount的值发生了变化,这就导致和expectedModCount的值相等了,故报错。
从源码中我们还得知,在clear方法,add方法,addAll方法,removeRange方法时都会导致modeCount的值发生变化。
所以当我们想在循环中对List进行删除时不能用List的remove*方法。但是可以用iterator.remove();从上面的源码中我们可以知道这个方法中进行了
expectedModCount=ModCount对expectedModCount重新赋值。
JAVA循环迭代中删除或添加集合数据报java.util.ConcurrentModificationException错误的更多相关文章
- 遍历List过程中删除操作报java.util.ConcurrentModificationException错误
1:遍历List 同时 remove 元素,出现java.util.ConcurrentModificationException错误 @Test public void test3(){ List& ...
- Java循环遍历中直接修改遍历对象
Java 循环遍历中直接修改遍历对象如下,会报异常: for (ShopBaseInfo sp: sourceList) { if(sp.getId()==5){ sourceList.remove( ...
- Java中删除第一个集合中以某某开头的元素,删除第二个集合中以某某结尾的元素,并合并成一个集合
import java.util.ArrayList; import java.util.List; public class Test { public static void main(Strin ...
- 【java】TreeMap/HashMap的循环迭代中 keySet和entrySet和forEach方式 + map的几种迭代方式
参考链接:https://www.cnblogs.com/crazyacking/p/5573528.html ================================== java紫色代表迭 ...
- java ArrayList迭代过程中删除
第一种迭代删除方式: 第二种迭代删除方式: 第三种迭代删除: 第四种迭代删除: 第五种迭代删除: 第六种: ArrayList中remove()方法的机制,首先看源码: 真正的删除操作在fastRem ...
- cmd中删除、添加、修改注册表命令
转自:http://www.jb51.net/article/30586.htm regedit的运行参数 REGEDIT [/L:system] [/R:user] filename1 REGEDI ...
- js实现在表格中删除和添加一行
<!DOCTYPE html><html> <head> <title> new document </title> <meta ht ...
- For循环List中删除正确的方式
单线程public class Test { public static void main(String[] args) { ArrayList<Integer> list = new ...
- Java 遍历List中删除的解决方法
随机推荐
- 第一次Java作业——简单的登录界面
千里之行,始于足下,从小做起,一点一滴学编程. import javax.swing.*; import java.awt.*; public class Homework{ public stati ...
- 什么是 SHTML
什么是 SHTML 使用SSI(Server Side Include)的html文件扩展名,SSI(Server Side Include),通常称为“服务器端嵌入”或者叫“服务器端包含”,是一种类 ...
- oc19--继承1
// // Phone.h // day13 #import <Foundation/Foundation.h> // 被继承的这个类我们称之为父类/ 超类 @interface Phon ...
- The Euler function(hdoj --2824-欧拉函数)
The Euler function Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...
- php 判断字符串包含中文(转)
$str = "测试中文"; echo $str; echo "<hr>"; //if (preg_match("/^[".ch ...
- 什么是CAS?
CAS(Compare-and-Swap),即比较并替换,是一种实现并发算法时常用到的技术,Java并发包中的很多类都使用了CAS技术.CAS需要有3个操作数:内存地址V,旧的预期值A,即将要更新的目 ...
- php对文件/目录操作的基础知识(图解)
具体的如下图所示:
- mysql连接出现error node【1045】
第一步:在my.ini下找到mysqlid.在后边添加skip-grant-tables 第二步:重新启动mysql服务 第三步:重新设置密码 第四步: 将skip-grant-tables删除掉,保 ...
- 图片文字滚动插件jQuery Scrollbox
图片文字滚动插件jQuery Scrollbox附件中提供了五种图片.文字滚动样式,只需调用jquery库和jQuery Scrollbox插件,然后再加一段简单的jquery代码即可使用,兼容性良好 ...
- 第九课: - 导出到CSV / EXCEL / TXT
第 9 课 将数据从microdost sql数据库导出到cvs,excel和txt文件. In [1]: # Import libraries import pandas as pd import ...