我希望能够在迭代过程中从集合中删除多个元素。最初,我希望迭代器足够聪明,以使下面的幼稚解决方案能够正常工作。
Set<SomeClass> set = new HashSet<SomeClass>(); fillSet(set); Iterator<SomeClass> it = set.iterator(); while (it.hasNext()) { set.removeAll(setOfElementsToRemove(it.next())); }
但这会引发一个错误ConcurrentModificationException。
ConcurrentModificationException
请注意,就我所知,iterator.remove()无法正常工作,因为我需要一次删除多个内容。还假设不可能确定“即时”删除哪些元素,但是可以编写该方法setOfElementsToRemove()。在我的特定情况下,要确定要在迭代过程中删除的内容,将占用大量内存和处理时间。由于内存限制,也无法制作副本。
setOfElementsToRemove()
setOfElementsToRemove()会生成一些我要删除的SomeClass实例集,并fillSet(set)用条目填充该集。
fillSet(set)
搜索堆栈溢出后,我找不到解决此问题的好方法,但是几个小时后,我意识到以下内容可以解决问题。
Set<SomeClass> set = new HashSet<SomeClass>(); Set<SomeClass> outputSet = new HashSet<SomeClass>(); fillSet(set); while (!set.isEmpty()) { Iterator<SomeClass> it = set.iterator(); SomeClass instance = it.next(); outputSet.add(instance); set.removeAll(setOfElementsToRemoveIncludingThePassedValue(instance)); }
setOfElementsToRemoveIncludingThePassedValue()将生成一组要删除的元素,其中包括传递给它的值。我们需要删除传递的值,因此set将为空。
setOfElementsToRemoveIncludingThePassedValue()
set
我的问题是,是否有人有更好的方法来执行此操作,或者是否有支持此类清除的收集操作。
另外,我认为我会发布解决方案,因为似乎有需要,我想贡献出色的资源,即Stack Overflow。
通常,当您在集合上循环时从集合中删除一个元素时,会收到Concurrent Modification Exception。这部分是为什么Iterator接口具有remove()方法的原因。使用迭代器是遍历元素时修改元素集合的唯一安全方法。
该代码将是这样的:
Set<SomeClass> set = new HashSet<SomeClass>(); fillSet(set); Iterator<SomeClass> setIterator = set.iterator(); while (setIterator.hasNext()) { SomeClass currentElement = setIterator.next(); if (setOfElementsToRemove(currentElement).size() > 0) { setIterator.remove(); } }
这样,您将安全地从setOfElementsToRemove()中删除所有生成删除集的元素。
编辑
根据对另一个答案的评论,这可能更是您想要的:
Set<SomeClass> set = new HashSet<SomeClass>(); Set<SomeClass> removalSet = new HashSet<SomeClass>(); fillSet(set); for (SomeClass currentElement : set) { removalSet.addAll(setOfElementsToRemove(currentElement); } set.removeAll(removalSet);