简体   繁体   English

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

[英]How to iterate over a SortedSet to modify items within

lets say I have an List. 我想说我有一个List。 There is no problem to modify list's item in for loop: 在for循环中修改list的项目没有问题:

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

But I have a SortedSet instead of list. 但是我有一个SortedSet而不是list。 How can I do the same with it? 我怎么能用它呢? Thank you 谢谢

First of all, Set assumes that its elements are immutable (actually, mutable elements are permitted, but they must adhere to a very specific contract, which I doubt your class does). 首先, Set假定它的元素是不可变的(实际上,可变元素允许的,但必须坚持一个非常具体的合同,我怀疑你的类一样)。

This means that generally you can't modify a set element in-place like you're doing with the list. 这意味着通常您不能像使用列表那样就地修改set元素。

The two basic operations that a Set supports are the addition and removal of elements. Set支持的两个基本操作是添加和删除元素。 A modification can be thought of as a removal of the old element followed by the addition of the new one: 可以将修改视为删除旧元素,然后添加新元素:

  1. You can take care of the removals while you're iterating, by using Iterator.remove() ; 通过使用Iterator.remove() ;您可以在迭代时处理删除。
  2. You could accumulate the additions in a separate container and call Set.addAll() at the end. 您可以在单独的容器中累积添加内容,并在末尾调用Set.addAll()

You cannot modify set's key, because it causes the set rehasing/reordering. 您无法修改set的密钥,因为它会导致设置重新定位/重新排序。 So, it will be undefined behaviour how the iteration will run further. 因此,迭代将如何进一步运行将是未定义的行为。

You could remove elements using iterator.remove(). 您可以使用iterator.remove()删除元素。 But you cannot add elements, usually better solution is to accumulate them in a new collection and addAll it after the iteration. 但是你不能添加元素,通常更好的解决方案是在新集合中累积它们并在迭代后添加它。

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

You should use an Iterator or better still the enhanced for-loop syntax (which depends on the class implementing the Iterable interface), irrespective of the Collection you're using. 您应该使用Iterator或更好的增强型for循环语法(这取决于实现Iterable接口的类),而不管您正在使用的Collection This abstracts away the mechanism used to traverse the collection and allows a new implementation to be substituted in without affecting the iteration routine. 这抽象出用于遍历集合的机制,并允许替换新实现而不影响迭代例程。

For example: 例如:

Set<Foo> set = ...

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

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

EDIT 编辑

Kan makes a good point regarding modifying the item's key. Kan对于修改项目的密钥提出了一个很好的观点。 Assuming that your class's equals() and hashCode() methods are based solely on the "id" attribute (which you're changing) the safest approach would be to explicitly remove these from the Set as you iterate and add them to an "output" Set ; 假设你的类的equals()hashCode()方法完全基于“id”属性(你正在改变),最安全的方法是在迭代时从Set显式删除它们并将它们添加到“输出” “ Set ; eg 例如

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.
}

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

You cannot do that. 你不能这样做。 But you may try, maybe you'll succeed, maybe you'll get ConcurrentModificationException . 但你可能会尝试,也许你会成功,也许你会得到ConcurrentModificationException It's very important to remember, that modifying elements while iterating may have unexpected results. 记住,在迭代时修改元素可能会产生意想不到的结果,这一点非常重要。 You should instead collect that elements in some collection. 您应该在某些集合中收集这些元素。 And after the iteration modify them one by one. 在迭代之后逐个修改它们。

This will only work, if id is not used for equals, or the comperator you used for the sorted set: 这只有在id不用于equals时才有效,或者用于排序集的comperator:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM