AFAIK,有两种方法:

迭代集合的副本 使用实际集合的迭代器

例如,

List<Foo> fooListCopy = new ArrayList<Foo>(fooList);
for(Foo foo : fooListCopy){
    // modify actual fooList
}

and

Iterator<Foo> itr = fooList.iterator();
while(itr.hasNext()){
    // modify actual fooList using itr.remove()
}

是否有任何理由偏爱一种方法而不是另一种方法(例如,出于可读性的简单原因而偏爱第一种方法)?


当前回答

有什么理由偏爱其中一种方法而不是另一种吗

第一种方法是可行的,但是有复制列表的明显开销。

第二种方法将不起作用,因为许多容器不允许在迭代期间进行修改。这包括数组列表。

如果唯一的修改是删除当前元素,则可以使用itr.remove()(即使用迭代器的remove()方法,而不是容器的remove()方法)来实现第二种方法。对于支持remove()的迭代器,这是我的首选方法。

其他回答

在Java 8中,还有另一种方法。# removeIf集合

eg:

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);

list.removeIf(i -> i > 2);

有什么理由偏爱其中一种方法而不是另一种吗

第一种方法是可行的,但是有复制列表的明显开销。

第二种方法将不起作用,因为许多容器不允许在迭代期间进行修改。这包括数组列表。

如果唯一的修改是删除当前元素,则可以使用itr.remove()(即使用迭代器的remove()方法,而不是容器的remove()方法)来实现第二种方法。对于支持remove()的迭代器,这是我的首选方法。

只有第二种方法有效。只能在迭代过程中使用iterator.remove()修改集合。所有其他尝试都会导致ConcurrentModificationException。

你不能做第二个,因为即使你在迭代器上使用remove()方法,你也会抛出一个异常。

就我个人而言,对于所有Collection实例,我更喜欢第一个,尽管创建新Collection需要额外的时间,但我发现它在其他开发人员编辑时不太容易出错。在某些Collection实现中,Iterator remove()是受支持的,而在其他实现中则不受支持。你可以在Iterator文档中阅读更多内容。

第三种选择是创建一个新的Collection,遍历原始Collection,并将第一个Collection中的所有成员添加到第二个Collection中不允许删除的成员。根据Collection的大小和删除的数量,与第一种方法相比,这种方法可以显著节省内存。

你可以看到这个例子;如果我们考虑从列表中移除奇数值:

public static void main(String[] args) {
    Predicate<Integer> isOdd = v -> v % 2 == 0;
    List<Integer> listArr = Arrays.asList(5, 7, 90, 11, 55, 60);
    listArr = listArr.stream().filter(isOdd).collect(Collectors.toList());
    listArr.forEach(System.out::println);
}