在迭代时从java中的集合中删除项目 [英] Removing items from a collection in java while iterating over it

查看:131
本文介绍了在迭代时从java中的集合中删除项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to be able to remove multiple elements from a set while I am iterating over it. Initially I hoped that iterators were smart enough for the naive solution below to work.

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()。在我的具体情况下,它需要大量的内存和处理时间来确定在迭代时要删除什么。进行复制也是不可能的,因为内存限制。

Note that iterator.remove() will not work as far as I can see because I need to remove multiple things at a time. Also assume that it is not possible to identify which elements to remove "on the fly", but it is possible to write the method setOfElementsToRemove(). In my specific case it would take up a lot of memory and processing time to determine what to remove while iterating. Making copies is also not possible because of memory constraints.

setOfElementsToRemove()将生成一些SomeClass实例,我要删除, fillSet(set)将填充条目。

setOfElementsToRemove() will generate some set of SomeClass instances that I want to remove, and fillSet(set) will fill the set with entries.

搜索Stack Overflow后,我找不到一个好的解决方案,几个小时后,我意识到以下会做这项工作。

After searching Stack Overflow I could not find a good solution to this problem but a few hours break later I realized the following would do the job.

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() will generate a set of elements to remove that includes the value passed to it. We need to remove the passed value so set will empty.

我的问题是,是否有更好的方法这样做或者是否有支持这些删除的收集操作。

My question is whether anyone has a better way of doing this or whether there are collection operations that support these kind of removals.

此外,我想我会发布我的解决方案,因为似乎有一个需要,我想

Also, I thought I would post my solution because there seems to be a need and I wanted to contribute the the excellent resource that is Stack Overflow.

推荐答案

通常当你从一个集合中移除一个元素,同时循环遍历集合时,您会收到并发修改异常 。这部分是为什么迭代器界面具有一个remove()方法。使用迭代器是遍历它们时修改元素集合的唯一安全方法。

Normally when you remove an element from a collection while looping over the collection, you'll get a Concurrent Modification Exception. This is partially why the Iterator interface has a remove() method. Using an iterator is the only safe way to modify a collection of elements while traversing them.

代码将会是这样:

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()中移除设置。

This way you'll safely remove all elements that generate a removal set from your setOfElementsToRemove().

EDIT

评论另一个答案,这可能更多你想要的:

Based on a comment to another answer, this may be more what you want:

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

这篇关于在迭代时从java中的集合中删除项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆