【发布时间】:2010-11-02 01:54:12
【问题描述】:
是否应该允许您从当前在 foreach 循环中迭代的集合中删除一个项目?
如果是这样,正确的行为应该是什么?
【问题讨论】:
-
编程语言?
标签: collections foreach iterator immutability
是否应该允许您从当前在 foreach 循环中迭代的集合中删除一个项目?
如果是这样,正确的行为应该是什么?
【问题讨论】:
标签: collections foreach iterator immutability
我可以使用相当复杂的集合来支持枚举器,这些枚举器可以跟踪集合的更改以保持位置信息正确。即使它确实需要做出一些妥协或假设。出于这个原因,大多数图书馆只是简单地禁止这样的事情或在他们的文档中抱怨意外的行为。
因此,最安全的方法是循环。收集对需要删除的事物的引用,然后使用收集到的引用从原始集合中删除项目。
【讨论】:
这真的取决于语言。有些人只是敲击一个阵列并在您更改该阵列时爆炸。有些使用数组并且不会爆炸。一些调用迭代器(它们更加健壮)并且运行良好。
【讨论】:
通常,在foreach 循环中修改集合是个坏主意,因为程序不知道您的意图。您的意思是在更改之前遍历所有项目,还是希望它只与新配置一起使用?已经循环的item呢?
相反,如果您想修改集合,请创建一个预定义的项目列表以进行循环,或使用索引循环。
【讨论】:
一些集合,如哈希表和字典,没有“位置”的概念,迭代的顺序一般也不能保证。因此,在迭代时允许删除项目是相当困难的。
【讨论】:
你必须先了解foreach的概念,实际上它取决于编程语言。但作为一般答案,您应该避免在 foreach 中更改您的集合
【讨论】:
只需使用标准的 for 循环,向后遍历项目集合,您应该可以随时删除项目。
【讨论】:
反向迭代并一个一个删除项目......这应该是正确的解决方案。
【讨论】:
不,你不应该。正确的行为应该是表示遇到了潜在的并发问题,但是这是用您选择的语言完成的(抛出异常、返回错误代码、raise() 一个信号)。
如果您在迭代其元素时修改数据结构,则迭代器可能不再有效,这意味着您可能会处理不再属于集合的对象。如果您想根据一些更复杂的符号过滤元素,您可以执行以下操作(在 Java 中):
List<T> toFilter = ...;
List<T> shadow;
for ( T element : toFilter )
if ( keep(element) )
shadow.add(element);
/* If you'll work with toFilter in the same context as the filter */
toFilter = shadow;
/* Alternatively, if you want to modify toFilter in place, for instance if it's
* been given as a method parameter
*/
toFilter.clear();
toFilter.addAll(shadow);
【讨论】:
从您正在迭代的集合中删除项目以显式使用迭代器的最佳方法。例如。
List<String> myList = ArrayList<String>();
Iterator<String> myIt = myList.iterator();
while (myIt.hasNext()) {
myIt.remove();
}
【讨论】: