如何在迭代它时覆盖Java中的HashSet元素

时间:2012-03-25 05:48:40

标签: java

是否有可能在迭代它时覆盖一些HashSet元素(不一定是迭代的)。我想知道除了删除,编辑然后重新添加它之外的一种方法吗? 我问这个的原因是因为在迭代时使用remove总是给出java.util.ConcurrentModificationException。我发现没有方法可以覆盖set元素。

任何帮助将不胜感激。

谢谢,

索姆纳特

4 个答案:

答案 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} - 即两个相等的元素。