Map<Warn,Object> map = new HashMap<>();
for(Entry<Warn,Object> entry : map.entrySet()){
...
...
map.remove(entry.getKey());
...
}
报错:java.util.ConcurrentModificationException异常。
后经查询,在进行迭代时,同时对其进行remove().操作会影响迭代。原因在于: 迭代器的modCount和expectedModCount的值不一致.
没有源码照片了。如果remove()后源码会判断值不一致,然后在hashMap中抛出java.util.ConcurrentModificationException异常.
这个问题需要了解一点:HashMap不是线程安全的,ConcurrentHashMap是线程安全的。
因此,解决这个问题就有一个了简单粗暴的方法,使用ConcurrentHashMap代替HashMap。亲测可用。
另外,还有一个方法,在修改HashMap的上下文进行加锁操作。但是效率太差或者占用内存太高。ConcurrentHashMap效率感觉快赶上不同步的速度。推荐。
List和Map等集合类都存在上述问题,还请注意
--------------------
以下为补充内容。方便以后学习。为转载文章。
Java在操作ArrayList、HashMap、TreeMap等容器类时,遇到了java.util.ConcurrentModificationException异常。以ArrayList为例,如下面的代码片段:
package sqlMap;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Test {
public static void main(String[] args) {
List<String> strList = new ArrayList<String>();
strList.add("string1");
strList.add("string2");
strList.add("string3");
strList.add("string4");
strList.add("string5");
strList.add("string6");
// 操作方式1:while(Iterator);报错
Iterator<String> it = strList.iterator();
while (it.hasNext()) {
String s = it.next();
if ("string2".equals(s)) {
strList.remove(s);
}
}
// 解决方案1:使用Iterator的remove方法删除元素
// 操作方式1:while(Iterator):不报错
// Iterator<String> it = strList.iterator();
// while(it.hasNext()) {
// String s = it.next();
// if("string2".equals(s)) {
// it.remove();
// }
// }
// 操作方式2:foreach(Iterator);报错
// for(String s : strList) {
// if("string2".equals(s)) {
// strList.remove(s);
// }
// }
// 解决方案2:不使用Iterator遍历,注意索引的一致性
// 操作方式3:for(非Iterator);不报错;注意修改索引
// for(int i=0; i<strList.size(); i++) {
// String s = strList.get(i);
// if("string2".equals(s)) {
// strList.remove(s);
// strList.remove(i);
// i--;
// 元素位置发生变化,修改i
// }
// }
// 解决方案3:新建一个临时列表,暂存要删除的元素,最后一起删除
// List<String> templist = new ArrayList<String>();
// for (String s : strList) {
// if(s.equals("string2")) {
// templist.add(s);
// }
// }
//
// 查看removeAll源码,其使用Iterator进行遍历
// strList.removeAll(templist);
// 解决方案4:使用线程安全CopyOnWriteArrayList进行删除操作
// List<String> strList = new CopyOnWriteArrayList<String>();
// strList.add("string1");
// strList.add("string2");
// strList.add("string3");
// strList.add("string4");
// strList.add("string5");
// strList.add("string6");
// Iterator<String> it = strList.iterator();
// while (it.hasNext()) {
// String s = it.next();
// if (s.equals("string2")) {
// strList.remove(s);
// }
// } } }
}
}
执行上述代码后,报错如下:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at concurrentModificationException.Test.main(Test.java:21)
在第21行报错,即it.next(),迭代器在获取下一个元素时报错。找到java.util.ArrayList第830行,看到it.next()的源代码,如下:
@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];
}
调用了checkForComodification()方法,代码如下:
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
以上部分内容为转载内容。原文链接:https://blog.csdn.net/kingzone_2008/article/details/41368989
来源:CSDN
作者:qq_24702263
链接:https://blog.csdn.net/qq_24702263/article/details/103810960