假设我有一个列表。在for循环中修改列表的项目没有问题:
for (int i = 0; i < list.size(); i++) { list.get(i).setId(i); }
但我有一个SortedSet而不是list。我怎么能用它呢? 谢谢
答案 0 :(得分:5)
首先,Set
假设其元素是不可变的(实际上,可变元素是允许的,但它们必须遵守一个非常具体的合同,我怀疑你的类是否合适)
这意味着通常您无法像使用列表那样就地修改设置元素。
Set
支持的两个基本操作是添加和删除元素。可以将修改视为删除旧元素,然后添加新元素:
Iterator.remove()
; 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++;
}