在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));
}

当前回答

那些说你不能安全地从集合中删除一个项的说法是不正确的,你可以使用一个并发集合,比如ConcurrentHashMap。

其他回答

我不知道迭代器,但是直到今天我才从循环中的列表中删除元素:

List<String> names = .... 
for (i=names.size()-1;i>=0;i--) {    
    // Do something    
    names.remove(i);
} 

这总是有效的,并且可以在其他不支持迭代器的语言或结构中使用。

确保这不是代码的味道。有可能颠倒逻辑,“包容”而不是“排他”吗?

List<String> names = ....
List<String> reducedNames = ....
for (String name : names) {
   // Do something
   if (conditionToIncludeMet)
       reducedNames.add(name);
}
return reducedNames;

将我引导到这个页面的情况涉及到使用indecies从List中删除元素循环遍历List的旧代码。我想重构它以使用foreach样式。

它循环遍历整个元素列表,以验证用户有权限访问哪些元素,并从列表中删除没有权限的元素。

List<Service> services = ...
for (int i=0; i<services.size(); i++) {
    if (!isServicePermitted(user, services.get(i)))
         services.remove(i);
}

要反转此操作而不使用remove:

List<Service> services = ...
List<Service> permittedServices = ...
for (Service service:services) {
    if (isServicePermitted(user, service))
         permittedServices.add(service);
}
return permittedServices;

什么时候“remove”更合适?一个考虑因素是,如果给定一个大列表或昂贵的“添加”,与列表大小相比,只删除了一些内容。只做少量的删除可能比大量的添加更有效。但在我的案例中,情况并不值得这样的优化。

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

因为删除的源代码是

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

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

是的你可以使用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

那些说你不能安全地从集合中删除一个项的说法是不正确的,你可以使用一个并发集合,比如ConcurrentHashMap。