小编典典

在Java集合上进行迭代时从集合中删除项目

java

我希望能够在迭代过程中从集合中删除多个元素。最初,我希望迭代器足够聪明,以使下面的幼稚解决方案能够正常工作。

Set<SomeClass> set = new HashSet<SomeClass>();
fillSet(set);
Iterator<SomeClass> it = set.iterator();
while (it.hasNext()) {
    set.removeAll(setOfElementsToRemove(it.next()));
}

但这会引发一个错误ConcurrentModificationException

请注意,就我所知,iterator.remove()无法正常工作,因为我需要一次删除多个内容。还假设不可能确定“即时”删除哪些元素,但是可以编写该方法setOfElementsToRemove()。在我的特定情况下,要确定要在迭代过程中删除的内容,将占用大量内存和处理时间。由于内存限制,也无法制作副本。

setOfElementsToRemove()会生成一些我要删除的SomeClass实例集,并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将为空。

我的问题是,是否有人有更好的方法来执行此操作,或者是否有支持此类清除的收集操作。

另外,我认为我会发布解决方案,因为似乎有需要,我想贡献出色的资源,即Stack Overflow。


阅读 222

收藏
2020-09-11

共1个答案

小编典典

通常,当您在集合上循环时从集合中删除一个元素时,会收到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);
2020-09-11