前言
Android开发中,使用ArrayList出现 Exception in thread “main” java.util.ConcurrentModificationException异常是比较常见的,部分日志如下:
Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901) at java.util.ArrayList$Itr.next(ArrayList.java:851)
记录一下相关知识,方便自己查阅。
本文内容大分部来源参考文。
正文
当checkForComodification()方法检测到对象的并发修改元素时,这是不允许的,因此会抛出ConcurrentModificationException。
原因
迭代器是依赖于集合而存在的,在判断成功后,集合的中新添加了元素,而迭代器却不知道,所以就报错了,这个错叫并发修改异常。
迭代器遍历元素的时候,通过集合是不能修改元素的。
下面分单线程和多线程分析。
单线程
List<String> myList = new ArrayList<String>(); myList.add("1"); myList.add("2"); myList.add("3"); myList.add("4"); myList.add("5");
下面三个例子遍历时并修改数据都会ConcurrentModificationException异常。
问题
例子
for (Iterator<String> it = myList.iterator(); it.hasNext(); ) { String value = it.next(); if (value.equals("3")) { myList.remove(value); } }
例子2
for (String value : myList) { if (value.equals("3")) { myList.remove(value); } }
例子3
Iterator<String> it = myList.iterator(); while (it.hasNext()) { String value = it.next(); if (value.equals("3")) { myList.remove(value); } }
解决方式
方式1
通过it移除
for (Iterator<String> it = myList.iterator(); it.hasNext(); ) { String value = it.next(); if (value.equals("3")) { it.remove(); } }
方式2
创建临时list记录需要移除的,然后统一移除。
List<String> templist = new ArrayList<String>(); for (String value : myList) { if (value.equals("3")) { templist.add(value); } } myList.removeAll(templist);
方式3
ArrayList改为CopyOnWriteArrayList
List<String> myList = new CopyOnWriteArrayList<>(); myList.add("1"); myList.add("2"); myList.add("3"); myList.add("4"); myList.add("5"); Iterator<String> it = myList.iterator(); while (it.hasNext()) { String value = it.next(); if (value.equals("3")) { myList.remove(value); } }
方式4
不使用Iterator进行遍历,需要注意的是自己保证索引正常
for ( int i = 0; i < myList.size(); i++) { String value = myList.get(i); if (value.equals( "3")) { myList.remove(value); i--; // 因为位置发生改变,所以必须修改i的位置 } }
多线程
单线程有问题,多线程也是存在的。
比如一个线程中添加元素,一个线程中删除元素。
解决方式,使用上面的方式4才有效。亲测。
List<String> myList = new CopyOnWriteArrayList<>(); myList.add("1"); myList.add("2"); myList.add("3"); myList.add("4"); myList.add("5"); new Thread(() -> { for (String string : myList) { Log.d(TAG, "run delete string : " + string); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); new Thread(() -> { for (int i = 0; i < myList.size(); i++) { String value = myList.get(i); if (value.equals("3")) { myList.remove(value); i--; } } }).start();
参考文章
《
© 版权声明