如何迭代SortedSet来修改其中的项目

时间:2011-11-29 12:51:27

标签: java iterator sortedset

假设我有一个列表。在for循环中修改列表的项目没有问题:

for (int i = 0; i < list.size(); i++) { list.get(i).setId(i); }

但我有一个SortedSet而不是list。我怎么能用它呢? 谢谢

6 个答案:

答案 0 :(得分:5)

首先,Set假设其元素是不可变的(实际上,可变元素允许的,但它们必须遵守一个非常具体的合同,我怀疑你的类是否合适)

这意味着通常您无法像使用列表那样就地修改设置元素。

Set支持的两个基本操作是添加和删除元素。可以将修改视为删除旧元素,然后添加新元素:

  1. 您可以在使用Iterator.remove();
  2. 进行迭代时处理删除操作
  3. 您可以在单独的容器中累积添加内容并在结尾处调用Set.addAll()

答案 1 :(得分:3)

您无法修改set的密钥,因为它会导致set rehasing / reordering。因此,迭代将如何进一步运行将是未定义的行为。

您可以使用iterator.remove()删除元素。但是你不能添加元素,通常更好的解决方案是在新集合中累积它们并在迭代后添加它。

Set mySet = ...;
ArrayList newElems = new ArrayList();

for(final Iterator it = mySet.iterator(); it.hasNext(); )
{
  Object elem = it.next();
  if(...)
   newElems.add(...);
  else if(...)
   it.remove();
  ...
}
mySet.addAll(newElems);

答案 2 :(得分:2)

您应该使用Iterator或更好的增强型for循环语法(这取决于实现Iterable接口的类),而不管您使用的Collection。这抽象出了用于遍历集合的机制,并允许在不影响迭代例程的情况下替换新的实现。

例如:

Set<Foo> set = ...

// Enhanced for-loop syntax
for (Foo foo : set) {
 // ...
} 

// Iterator approach
Iterator it = set.iterator();
while (it.hasNext()) {
  Foo foo = it.next();
}

修改

Kan在修改项目密钥时提出了一个很好的观点。假设您的班级的equals()hashCode()方法仅基于“id”属性(您正在更改),最安全的方法是明确地从Set中删除这些属性迭代并将它们添加到“输出”Set; e.g。

SortedSet<Foo> input = ...
SortedSet<Foo> output = new TreeSet<Foo>();

Iterator<Foo> it = input.iterator();
while (it.hasNext()) {
  Foo foo = it.next();
  it.remove(); // Remove from input set before updating ID.
  foo.setId(1);
  output.add(foo); // Add to output set.
}

答案 3 :(得分:2)

从Java 1.6开始,您就可以使用NavigableSet

答案 4 :(得分:2)

你做不到。但你可以试试,也许你会成功,也许你会得到ConcurrentModificationException。记住,在迭代时修改元素可能会产生意想不到的结果,这一点非常重要。您应该在某些集合中收集这些元素。在迭代之后逐个修改它们。

答案 5 :(得分:1)

仅当id未用于equals或用于sortedset的比较器时,此操作才有效:

int counter = 0;
for(ElementFoo e : set) {
  e.setId(counter);
  couter++;
}