简体   繁体   English

迭代java中的TreeSet并更新它

[英]Iterating through a TreeSet in java and updating it

I have a TreeSet in Java and I have my own comparator function for this tree set. 我在Java中有一个TreeSet ,我有自己的比较器函数用于这个树集。 Now I am traversing this tree set using descendingIterator() method and changing the elements. 现在我使用descendingIterator()方法遍历此树集并更改元素。 So does this update the actual tree set as well wrt to the way it is sorted with my custom comparator? 那么这会更新实际树集以及使用我的自定义比较器排序的方式吗? Or do I need to remove the element and put back the updated element? 或者我是否需要删除元素并放回更新的元素?

You need to remove the element and add it back. 您需要删除元素并将其添加回来。 The position of the element in the tree is decided when the element is inserted, by comparing it with other elements. 通过将元素与其他元素进行比较,在插入元素时决定树中元素的位置。 If you change the object so that the comparison to other elements changes, you must remove the element first, then change it, then re-add it. 如果更改对象以便与其他元素进行比较更改,则必须先删除元素,然后更改它,然后重新添加。

Note that removing the element while iterating will only work using the iterator's remove method. 请注意,迭代时删除元素只能使用迭代器的remove方法。 And you won't be able to add it during the iteration without getting a ConcurrentModificationException, AFAIK. 如果没有获得ConcurrentModificationException,AFAIK,您将无法在迭代期间添加它。 So store it in a list of elements to be re-added to the set once the iteration has ended. 因此,一旦迭代结束,将其存储在要重新添加到集合的元素列表中。

If you modify any part of the object that is a part of the "key" (as defined by your custom comparator) you need to remove and re-insert the object for the tree set to "learn" about the change. 如果修改作为“键”一部分的对象的任何部分(由自定义比较器定义),则需要删除并重新插入树集的对象以“学习”有关更改的内容。 You should not be doing it while you are iterating, either: a good approach is to collect items that need changing in one loop, and then modify and re-insert them in another loop. 在迭代时你不应该这样做:一个好的方法是收集需要在一个循环中更改的项目,然后在另一个循环中修改并重新插入它们。

As a general rule of thumb, it isn't advisable to "modify" any value types added to Java containers which rely on equality, hash code etc. given that none of the known standard containers perform auto-balancing or adjustment in response to the change of values (which makes sense). 作为一般的经验法则,不建议“修改”添加到依赖于相等,哈希码等的Java容器的任何值类型,因为没有任何已知的标准容器执行自动平衡或调整以响应价值观的变化(这是有道理的)。

Along with Set , this rule is equally valid for Map types. Set ,此规则对Map类型同样有效。 If you are iterating over a map and modify the "key" in-place, things go bad. 如果您在地图上迭代并在原地修改“密钥”,那么事情就会变得糟糕。 This is the reason why it is recommended to have immutable types as your Map keys (think of String , Integer etc.) Your case can be demonstrated by a simple example: 这就是为什么建议将不可变类型作为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]]

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

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