ArrayList同时读写造成java.util.ConcurrentModificationException异常
在ArrayList同时读写时,会造成java.util.ConcurrentModificationException异常。该读写包括同时调用ArrayList的add、remove、size、addAll、set、get等方法,都会报该异常。
该异常的本质是调用上述方法List中modCount就会变化,如果这个modCount和exceptedModCount不一致,就会抛出异常。具体的场景有以下几种:使用forEach遍历时删除元素、多线程同时读写。
那如何避免该问题呢?遍历时删除元素,不要使用forEach遍历即可。 foreach方式遍历元素的时候会生成iterator,然后使用iterator遍历。同时iterator会保存一个expectedModCount参数。该参数表示List中修改元素的次数。如果在遍历过程中删除元素,List中modCount就会变化,如果modCount和exceptedModCount不一致,就会抛出异常。
如果使用iterator的remove方法则会正常,因为iterator的remove方法会在内部调用List的remove方法,但是会修改excepedModCount的值,因此会正常运行。以下是使用遍历同时删除元素不报异常的实例:
1、倒序遍历 List ,如果找到元素,则使用 remove 方法进行移除:
List<String> list = new ArrayList<>();
list.add("第一代码");
list.add("知音简历");
list.add("免费简历");
list.add("简历模板");
list.add("免费范文");
for (int i = list.size() - 1; i > 0; i--) {
if("简历模板".equals(list.get(i))){
list.remove(i);
}
}
System.out.println(list);
2、使用 Iterator ,顺序向下,如果找到元素,则使用 remove 方法进行移除:
List<String> list = new ArrayList<>();
list.add("第一代码");
list.add("知音简历");
list.add("免费简历");
list.add("简历模板");
list.add("免费范文");
// 获取迭代器
Iterator<String> it = list.iterator();
while(it.hasNext()){
String str = it.next();
if("第一代码".equals(str)){
it.remove();
}
}
System.out.println(list);
3、正序遍历 List ,如果找到元素,则使用 remove 方法进行移除,然后进行索引自减:
List<String> list = new ArrayList<>();
list.add("第一代码");
list.add("知音简历");
list.add("免费简历");
list.add("简历模板");
list.add("免费范文");
for (int i = 0; i < list.size(); i++) {
if("知音简历".equals(list.get(i))){
list.remove(i);
i--;
}
}
System.out.println(list);
4、使用jdk1.8新增的Stream流操作:
List<String> list = new ArrayList<>();
list.add("第一代码");
list.add("知音简历");
list.add("免费简历");
list.add("简历模板");
list.add("免费范文");
// 筛选出不是“第一代码” 的集合
list = list.stream().filter(e -> !"第一代码".equals(e)).collect(Collectors.toList());
System.out.println("method4|list=" + list);
以下是使用多线程读写不报异常的实例,可添加synchronized 同步锁防止异常:
List<String> list = new ArrayList<>();
synchronized (list) {
list.add("第一代码");
list.add("知音简历");
list.add("免费简历");
list.add("简历模板");
list.add("免费范文");
System.out.println(list.get(0));
}
synchronized (list) {
for (int i = list.size() - 1; i > 0; i--) {
if ("简历模板".equals(list.get(i))) {
list.remove(i);
}
}
System.out.println(list);
}
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。



