循环列表中删除

eng*_*ran 40 java collections

    for (String fruit : list)
    {
        if("banane".equals(fruit))
            list.remove(fruit);
        System.out.println(fruit);
    }
Run Code Online (Sandbox Code Playgroud)

这里有一个带删除指令的循环.在执行时,我在控制台输出下面得到一些ConcurrentModificationException:

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:449)
at java.util.AbstractList$Itr.next(AbstractList.java:420)
at Boucle.main(Boucle.java:14)
abricot
banane
Run Code Online (Sandbox Code Playgroud)

问题:如何用循环删除一些元素?

Jon*_*eet 85

您需要直接使用迭代器,并通过该迭代器删除该项.

for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
    String fruit = iterator.next();
    if ("banane".equals(fruit)) {
        iterator.remove();
    }
    System.out.println(fruit);
}
Run Code Online (Sandbox Code Playgroud)


小智 12

这看起来有点复杂,为什么不只是做一个正常的循环?我认为它看起来更干净,不会抛出这个错误.如果你删除了某些内容,请记下我.无论如何,至少我的工作.我认为,那些类型的自动循环更多是为了方便编码,所以如果它们不方便那么就不要使用它们.

for (int i = list.size() - 1; i>=0; i--) {
    String fruit = list.get(i);
    System.out.println(fruit);

    if ("banane".equals(fruit)) {
        list.remove(fruit);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这在大型列表上会非常慢(算法术语中的`O(n^2)`),因为`List#remove(Object)` 需要通过对给定对象的列表执行线性搜索来重做工作。如果可能,最好使用索引,这将使它的时间为“O(n)”。 (4认同)

Bom*_*mbe 6

除了Iterator直接使用(我建议使用)之外,您还可以将要删除的元素存储在不同的列表中.

List<String> toRemove = new ArrayList<String>();
for (String fruit : list) {
    if ("banane".equals(fruit))
        toRemove.add(fruit);
    System.out.println(fruit);
}
for (String fruit : toRemove) {
    list.remove(fruit);
}
Run Code Online (Sandbox Code Playgroud)

请注意,我不推荐这个,它只是一个替代方案.:)

  • "错误"也有不止一个含义.:) (3认同)
  • 是的.这就是为什么我会使用基于`Iterator`的解决方案 - 这就是我所写的. (2认同)

Fre*_*els 5

使用 for 循环,并以相反的顺序循环遍历集合。(这意味着,从最后一个元素开始,然后循环到第一个元素。这样做,您不会因为从集合中删除元素而更改索引而遇到问题。

您在发布的示例中遇到异常,因为您的迭代器迭代的列表已更改,这意味着迭代器变得无效。