关于java:使用remove删除列表

loop on list with remove

本问题已经有最佳答案,请猛点这里访问。
1
2
3
4
5
6
    for (String fruit : list)
    {
        if("banane".equals(fruit))
            list.remove(fruit);
        System.out.println(fruit);
    }

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

1
2
3
4
5
6
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

问题:如何用循环移除某些元素?


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

1
2
3
4
5
6
7
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
    String fruit = iterator.next();
    if ("banane".equals(fruit)) {
        iterator.remove();
    }
    System.out.println(fruit);
}


这看起来有点复杂,为什么不做一个正常的for循环呢?我认为它看起来更干净,不会抛出这个错误。如果你把什么东西拿走,我就谴责你。不管怎样,至少我的工作。我想,这种自动循环更多的是为了方便编码,所以如果它们不方便,就不要使用它们。

1
2
3
4
5
6
7
8
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);
    }
}


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

1
2
3
4
5
6
7
8
9
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);
}

注意,我不推荐这个,这只是一个选择。:)


1
2
3
4
5
6
7
for(Iterator<String> iter = list.iterator(); iter.hasNext(); )
{
   String fruit = iter.next();
   if("banana".equals(fruit))
      iter.remove();
   System.out.println(fruit);
}

使用for循环,并按相反顺序循环集合。(也就是说,从最后一个元素开始,循环到第一个元素。这样做,就不会因为从集合中删除元素而被更改的索引带来问题。

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


1
2
3
4
5
6
7
8
9
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a","b","c","d"));
Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
    String s = iter.next();

    if (s.equals("a")) {
        iter.remove();
    }
}

是最好的方法。


类似于bombe的建议,但是通过迭代列表副本减少了代码行,但是从原始列表中删除了代码行;

1
2
3
4
5
6
7
List<String> temp = new ArrayList<String>(list);
for (String fruit : temp)
{
    if("banane".equals(fruit))
        list.remove(fruit);
    System.out.println(fruit);
}

我个人认为这比用迭代器迭代更好。