在Java中,当使用foreach循环遍历集合时,对集合调用remove是否合法?例如:

List<String> names = ....
for (String name : names) {
   // Do something
   names.remove(name).
}

作为附录,移除尚未迭代的项目是否合法?例如,

//Assume that the names list as duplicate entries
List<String> names = ....
for (String name : names) {
    // Do something
    while (names.remove(name));
}

当前回答

“增强型for循环”的java设计是不向代码公开迭代器,但安全删除项的唯一方法是访问迭代器。所以在这种情况下,你得用老办法:

 for(Iterator<String> i = names.iterator(); i.hasNext();) {
       String name = i.next();
       //Do Something
       i.remove();
 }

如果在实际代码中,增强的for循环确实值得这样做,那么您可以将这些项添加到临时集合中,并在循环之后调用列表上的removeAll。

EDIT(重编):不,在迭代时以iterator.remove()方法之外的任何方式更改列表都会导致问题。解决这个问题的唯一方法是使用CopyOnWriteArrayList,但这实际上是为了解决并发问题。

删除重复项最便宜的方法(就代码行数而言)是将列表转储到LinkedHashSet中(如果需要,再转储回list中)。这样可以在删除重复项的同时保留插入顺序。

其他回答

当您想要从列表中删除元素时,最好使用迭代器

因为删除的源代码是

if (numMoved > 0)
    System.arraycopy(elementData, index+1, elementData, index,
             numMoved);
elementData[--size] = null;

所以,如果你从列表中删除一个元素,列表将被重构,其他元素的索引将被改变,这可能会导致你想要发生的事情。

你不会想这么做的。它可能导致未定义的行为,具体取决于集合。你想直接使用迭代器。虽然for每个构造都是语法糖,并且实际上使用了迭代器,但它对代码隐藏了迭代器,因此您无法访问它来调用iterator .remove。

迭代器的行为是 未指定,如果基础 属性时,将对集合进行修改 迭代正在以任何方式进行 除了调用这个方法。

相反,编写代码:

List<String> names = ....
Iterator<String> it = names.iterator();
while (it.hasNext()) {

    String name = it.next();
    // Do something
    it.remove();
}

注意,代码调用Iterator。remove,而不是List.remove。

附录:

即使您正在删除一个尚未迭代的元素,您仍然不想修改集合,然后使用Iterator。它可能会以一种令人惊讶的方式修改集合,并影响Iterator上的后续操作。

Use

.remove() Interator或

Use

CopyOnWriteArrayList

“增强型for循环”的java设计是不向代码公开迭代器,但安全删除项的唯一方法是访问迭代器。所以在这种情况下,你得用老办法:

 for(Iterator<String> i = names.iterator(); i.hasNext();) {
       String name = i.next();
       //Do Something
       i.remove();
 }

如果在实际代码中,增强的for循环确实值得这样做,那么您可以将这些项添加到临时集合中,并在循环之后调用列表上的removeAll。

EDIT(重编):不,在迭代时以iterator.remove()方法之外的任何方式更改列表都会导致问题。解决这个问题的唯一方法是使用CopyOnWriteArrayList,但这实际上是为了解决并发问题。

删除重复项最便宜的方法(就代码行数而言)是将列表转储到LinkedHashSet中(如果需要,再转储回list中)。这样可以在删除重复项的同时保留插入顺序。

是的你可以使用for-each循环, 要做到这一点,你必须维护一个单独的列表来保存删除项,然后使用removeAll()方法从名称列表中删除该列表,

List<String> names = ....

// introduce a separate list to hold removing items
List<String> toRemove= new ArrayList<String>();

for (String name : names) {
   // Do something: perform conditional checks
   toRemove.add(name);
}    
names.removeAll(toRemove);

// now names list holds expected values