[java] 如何避免“ConcurrentModificationException”同时从`ArrayList`中移除元素时迭代它?


Answers

作为别人答案的替代方案,我总是这样做:

List<String> toRemove = new ArrayList<String>();
for (String str : myArrayList) {
    if (someCondition) {
        toRemove.add(str);
    }
}
myArrayList.removeAll(toRemove);

这将避免你必须直接处理迭代器,但需要另一个列表。 无论出于何种原因,我总是喜欢这条路线。

Question

我试图从ArrayList删除一些元素,而像这样迭代它:

for (String str : myArrayList) {
    if (someCondition) {
        myArrayList.remove(str);
    }
}

当然,当迭代myArrayListConcurrentModificationException尝试从列表中删除项目时,我会遇到ConcurrentModificationException myArrayList 。 有一些简单的解决方案来解决这个问题吗?




您可以使用迭代器remove()函数从底层集合对象中删除该对象。 但在这种情况下,您可以从列表中删除同一个对象,而不是其他任何对象。

here




虽然其他建议的解决方案的工作,如果你真的想让解决方案成为线程安全的,你应该用CopyOnWriteArrayList替换ArrayList

    //List<String> s = new ArrayList<>(); //Will throw exception
    List<String> s = new CopyOnWriteArrayList<>();
    s.add("B");
    Iterator<String> it = s.iterator();
    s.add("A");

    //Below removes only "B" from List
    while (it.hasNext()) {
        s.remove(it.next());
    }
    System.out.println(s);



一种替代方法是将List转换为array ,根据您的逻辑对它们进行迭代并直接从List删除它们。

List<String> myList = new ArrayList<String>(); // You can use either list or set

myList.add("abc");
myList.add("abcd");
myList.add("abcde");
myList.add("abcdef");
myList.add("abcdefg");

Object[] obj = myList.toArray();

for(Object o:obj)  {
    if(condition)
        myList.remove(o.toString());
}



你必须使用迭代器的remove()方法,这意味着没有增强的for循环:

for (final Iterator iterator = myArrayList.iterator(); iterator.hasNext(); ) {
    iterator.next();
    if (someCondition) {
        iterator.remove();
    }
}





Related