[英]How to iterate over a SortedSet to modify items within
我想說我有一個List。 在for循環中修改list的項目沒有問題:
for (int i = 0; i < list.size(); i++) { list.get(i).setId(i); }
但是我有一個SortedSet而不是list。 我怎么能用它呢? 謝謝
首先, Set
假定它的元素是不可變的(實際上,可變元素是允許的,但必須堅持一個非常具體的合同,我懷疑你的類一樣)。
這意味着通常您不能像使用列表那樣就地修改set元素。
Set
支持的兩個基本操作是添加和刪除元素。 可以將修改視為刪除舊元素,然后添加新元素:
Iterator.remove()
;您可以在迭代時處理刪除。 Set.addAll()
。 您無法修改set的密鑰,因為它會導致設置重新定位/重新排序。 因此,迭代將如何進一步運行將是未定義的行為。
您可以使用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);
您應該使用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
; 例如
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
。
你不能這樣做。 但你可能會嘗試,也許你會成功,也許你會得到ConcurrentModificationException
。 記住,在迭代時修改元素可能會產生意想不到的結果,這一點非常重要。 您應該在某些集合中收集這些元素。 在迭代之后逐個修改它們。
這只有在id
不用於equals時才有效,或者用於排序集的comperator:
int counter = 0;
for(ElementFoo e : set) {
e.setId(counter);
couter++;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.