问题
我有一个我想迭代的ArrayList。迭代它时,我必须同时删除元素。显然这会引发ajava.util.ConcurrentModificationException
。
处理此问题的最佳做法是什么?我应该先克隆列表吗?
我删除不在循环本身的元素,而是删除代码的另一部分。
我的代码如下所示:
public class Test() {
private ArrayList<A> abc = new ArrayList<A>();
public void doStuff() {
for (A a : abc)
a.doSomething();
}
public void removeA(A a) {
abc.remove(a);
}
}
a.doSomething
可以致电Test.removeA()
;
#1 热门回答(218 赞)
两种选择:
- 创建一个要删除的值列表,在循环中添加到该列表,然后在末尾调用originalList.removeAll(valuesToRemove)
- 在迭代器本身上使用remove()方法。请注意,这意味着你无法使用增强型for循环。
作为第二个选项的示例,从列表中删除长度大于5的任何字符串:
List<String> list = new ArrayList<String>();
...
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
String value = iterator.next();
if (value.length() > 5) {
iterator.remove();
}
}
#2 热门回答(13 赞)
来自ArrayList的JavaDocs
通过此类的iterator和listIterator方法返回的迭代器是快速失败的:如果列表随时结构上修改迭代器创建之后,以任何方式,除了通过迭代器自身的remove或add方法,迭代器都将抛出ConcurrentModificationException 。
#3 热门回答(7 赞)
你应该以传统方式迭代数组
每次从列表中删除元素时,后面的元素都将向前推进。只要你不更改迭代之外的元素,以下代码就可以工作。
public class Test(){
private ArrayList<A> abc = new ArrayList<A>();
public void doStuff(){
for(int i = (abc.size() - 1); i >= 0; i--)
abc.get(i).doSomething();
}
public void removeA(A a){
abc.remove(a);
}
}