是否有可能在迭代它时覆盖一些HashSet元素(不一定是迭代的)。我想知道除了删除,编辑然后重新添加它之外的一种方法吗? 我问这个的原因是因为在迭代时使用remove总是给出java.util.ConcurrentModificationException。我发现没有方法可以覆盖set元素。
任何帮助将不胜感激。
谢谢,
索姆纳特
答案 0 :(得分:3)
您可以删除Collection
中的某个项目 - 包括Set
- 同时迭代它,只要您使用Iterator
进行迭代并调用Itertator.remove()
即可删除。但是,这只允许您删除迭代中的当前项。
您无法删除其他项目或添加一项,因为这会导致ConcurrentModificationException
,因为如果更改Set
,则不清楚如何迭代它。
此外,与List
不同,谈论替换 Set
中的条目是没有意义的。在List
项目中有一个定义顺序,例如,如果第二个条目是“A”,则可以用“B”替换它。 Set
中的项目没有订单,因此您无法直接替换另一个订单,您可以做的就是删除旧订单并添加新订单。
完全取决于您想要做什么,您最好的方法可能是循环遍历Set
的副本:
Set<Object> originalSet = someMethod();
for (Object item : new HashSet<Object>(originalSet)) {
//do stuff which modifies originalSet
}
但是,您必须考虑到您迭代的对象将是原始值,并且不会反映您所做的任何更改。
如果不这样做,那么找到另一种处理Set
中项目的方法可能是有意义的,而不是简单地通过跟踪你已处理的节点来迭代它们。
这样的事情可能会发生,但可能会根据你正在做的事情进行改进:
Set<Object> originalSet = somemethod();
//Keep track of items we've already processed
Set<Object> processed = new HashSet<Object>();
//toDo is used to calculate which items in originalSet aren't in processed
Set<Object> toDo = new HashSet(originalSet);
toDo.removeAll(processed);
while (! toDo.isEmpty()) {
//Get an object from toDo
Object item = toDo.iterator().next();
//Do some processing
//Can update originalSet or even remove from processed if we want to re-do an item
//Recalculate what's left to do
processed.add(item);
toDo = new HashSet(originalSet);
toDo.removeAll(processed);
}
答案 1 :(得分:2)
Set<Key> set = Sets.newHashSet();
// ...
for (Key k : ImmutableSet.copyOf(set)) {
if (needToMessWith(k)) {
set.remove(k);
k.mutateAsNeeded();
set.add(k);
}
}
//我使用了guava集合代码。这很简单,没有。
答案 2 :(得分:1)
只需将设置转换为列表并使用set()
,完成后将其转换为Set
或维护另一个Set
答案 3 :(得分:1)
没有办法做到这一点。因为替换元素基本上是删除+插入。 这是一个集合,而不是列表。例如,集合{1,2}中有两个元素,您希望将{1}替换为{2}。这是不可能的,因为结果集不能包含{2,2} - 即两个相等的元素。