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中删除的解决方法
随机推荐
- [Linux]非常方便的上传下载文件工具rz和sz
linux上非常方便的上传下载文件工具rz和sz (本文适合linux入门的朋友) [一般用于SecureCRT ssh中使用] █ 法一:直接用yum安装lrzsz(推荐) yum insta ...
- luogu1967 货车运输 最大瓶颈生成树
题目大意 给出一张图,给出q对点,求这两个点间权值最小边最大的路径,输出这个最小边权. 题解 我们先一条一条边建图.当建立的边使得图中形成环时,因为环中的每个节点只考虑是否连通和瓶颈大小,要想互相连通 ...
- Triangle LOVE(拓扑排序)
Triangle LOVE Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/65536K (Java/Other) Total ...
- [转载]ROS_LOG保存方法
原文地址:ROS_LOG保存方法作者:东咚... 把Service中的WWW的IP设置为允许日志保存服务器访问的范围 System->Logging,点击 "Actions" ...
- Email非正则表达式的判断
判断一个邮件是否合法,我们除了可以使用正则表达四以外还可以利用,Email地址的规律进行判断,那么一个合法的Email有哪些要求昵?具体如下: 必须有@与. @必须在第一个.之前 @与.不能连在一起 ...
- 在量化金融中15个最流行的Python数据分析库
Python是当今应用最广泛的编程语言之一,以其效率和代码可读性著称.作为一个科学数据的编程语言,Python介于R和java之间,前者主要集中在数据分析和可视化,而后者主要应用于大型应用.这种灵活性 ...
- 数据科学的完整学习路径(Python版)
转载自:http://python.jobbole.com/80981/ 英文(原文)连接:https://www.analyticsvidhya.com/learning-paths-data-sc ...
- Python3没有dict.has_key方法
最近开始学习Python,安装上最新的Python3.3.3照书敲了一个小程序结果报错 'dict' object has no attribute 'has_key' 上网查也找不到解决办法,后来发 ...
- C# txt文件操作
//打开文件到流 FileStream fs=new FileStream(path,FileMode.Open,FileAccess.ReadWrite); //写文件流的方法 StreamWrit ...
- MapReduce架构与生命周期
MapReduce架构与生命周期 概述:MapReduce是hadoop的核心组件之一,可以通过MapReduce很容易在hadoop平台上进行分布式的计算编程.本文组织结果如下:首先对MapRedu ...