2012-01-01 36 views
4

我在Java中有一個TreeSet,我對這個樹集有我自己的比較函數。現在我使用descendingIterator()方法遍歷這個樹集並更改元素。那麼這是否更新了實際的樹集以及它與我的自定義比較器的排序方式?或者我需要刪除元素並放回更新的元素?在Java中迭代TreeSet並更新它

+0

發佈您的代碼。 – Lion 2012-01-01 17:23:21

+0

它的長代碼和一些大代碼的一部分,所以不能把代碼,所以可以有人在概念上解釋,如果這正確或不 – lancelot 2012-01-01 17:29:26

回答

8

您需要刪除該元素並將其添加回來。通過與其他元素進行比較,插入元素時決定元素在樹中的位置。如果您更改對象以便與其他元素的比較發生更改,則必須先刪除該元素,然後對其進行更改,然後重新添加。

請注意,迭代時刪除元素只能使用迭代器的remove方法。在迭代期間,您將無法添加它,但不會收到ConcurrentModificationException AFAIK。因此,一旦迭代結束,將其存儲在要重新添加到集合的元素列表中。

+0

感謝您的答覆! – lancelot 2012-01-01 17:31:34

3

如果您修改屬於「鍵」(由您的自定義比較器定義)的一部分的對象的任何部分,您需要刪除並重新插入樹的對象以設置爲「瞭解」該變化。在迭代時,你不應該這樣做:好的方法是收集需要在一個循環中更改的項目,然後修改並在另一個循環中重新插入它們。

1

作爲一般的經驗法則,如果沒有已知的標準容器執行自動平衡或調整,則不建議「添加」添加到Java容器的任何值類型,這些類型依賴於相等性,散列碼等以迴應價值的變化(這是有道理的)。

Set一起,此規則對於Map類型同樣有效。如果你正在迭代地圖並在原地修改「密鑰」,事情就會變糟。這就是爲什麼我們建議有穩定的類型爲您的地圖鍵(想StringInteger等)的情況下,您可以通過一個簡單的例子來說明的理由:你想

public class Test {   
    public static void main(final String[] args) { 
     Mutable m1 = new Mutable(1); 
     Mutable m2 = new Mutable(2); 
     Mutable m3 = new Mutable(3); 
     Mutable m4 = new Mutable(4); 
     TreeSet<Mutable> ts = new TreeSet<Mutable>(new Cmp()); 
     ts.add(m1); ts.add(m2); ts.add(m3); ts.add(m4); 
     System.out.println(ts); 
     for (Iterator<Mutable> iter = ts.iterator(); iter.hasNext();) { 
      Mutable m = iter.next(); 
      if (m.i == 1 || m.i == 3) { 
       m.i = m.i + 10;     
      } 
     } 
     System.out.println(ts); 
    }   
}  
class Mutable {   
    public int i;   
    public Mutable(int i) { 
     this.i = i; 
    }   
    public String toString() { 
     return "Mutable[" + i + "]"; 
    }   
}  
class Cmp implements Comparator<Mutable> {  
    @Override public int compare(Mutable o1, Mutable o2) { 
     return Integer.valueOf(o1.i).compareTo(Integer.valueOf(o2.i)); 
    }   
} 

Output: 

[Mutable[1], Mutable[2], Mutable[3], Mutable[4]] 
[Mutable[11], Mutable[2], Mutable[13], Mutable[4]]