2012-01-01 126 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]]