这个操作安全吗?
这个操作安全吗? 如果没有,为了做同样的事情,如何编写代码?
Set<Object> set;
......
for (Object o: set) {
if (some_condition) {
set.remove(o);
}
}
Is this operation safe?
if not, in order to do the same thing, how to write the code??
Set<Object> set;
......
for (Object o: set) {
if (some_condition) {
set.remove(o);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
不,不是 - 因为除了通过迭代器之外,您不允许修改正在迭代的集合。有多种选项可以解决此问题。这是一个:
另一种选择是构建一个单独的要删除的项目列表,然后在迭代该集合后将它们全部删除:
No, it's not - because you aren't allowed to modify a collection you're iterating over, other than via the iterator. There are various options for fix this. Here's one:
Another option is to build a separate list of items to remove, and then remove them all after you've iterated over the set:
否 - 第一次通过条件时,您将在下一次迭代中抛出
ConcurrentModificationException
。一般来说,在迭代集合时直接修改集合是不安全的,并且迭代器在这种情况下是“快速失败”的(因为总的来说,虽然它们可以检测更改,但没有通用的方法找出如何应对它们)。
在这种情况下,一种有效的习惯用法是使用 Iterator 自己的
remove()
方法。以这种受控方式删除元素可以使迭代器了解正在发生的情况,并且对于迭代顺序应该发生的情况具有一致的语义,因此可以按照您的预期工作:但请注意
remove()
是一个“可选操作”,并非所有集合的迭代器都支持它。如果您陷入这种情况,始终有效的替代方法是获取该集合的副本,迭代该并从原始集合中删除对象,像这样:因为迭代已经结束了
copy
,而修改发生在set
上,所以不会发生并发修改,迭代器很高兴。No - the first time your condition passes, you'll get a
ConcurrentModificationException
thrown on the next iteration.In general, it is not safe to modify a collection directly while iterating over it, and iterators are "fail-fast" in this situation (because on the whole while they can detect changes, there's no general way to work out how to cope with them).
In this situation, one idiom that does work is to use the Iterator's own
remove()
method. Removing the element in this controlled fashion keeps the iterator aware of what is happening, and has consistent semantics for what should happen to the iteration order, and so works as you would expect:Note however that
remove()
is an "optional operation", and not all collections' iterators support it. If you're stuck in this situation, an alternative that will always work is to take a copy of the set, iterate over that and remove the objects from the original set, like so:Because the iteration is over
copy
, while the modifications happen toset
, no concurrent modification occurs and the iterator is happy.现在,它将抛出一个
ConcurrentModificationException
。for()
循环在内部使用Iterator
来保存编辑计数,如果该编辑计数与支持Set
的编辑不匹配计数,它会抛出一个 ConcurrentModificationException当然这取决于集合的实际实现,但这是记录的行为,例如在
HashSet
文档:Now, it will throw a
ConcurrentModificationException
.The
for()
loop uses anIterator
internally that keeps an edit count and if that edit count doesn't match the backingSet
's edit count, it throws aConcurrentModificationException
Of course this depends on the actual implementation of the collection, but that's the documented behavior, e.g. in the
HashSet
docs: