繁体   English   中英

迭代java中的TreeSet并更新它

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

我在Java中有一个TreeSet ,我有自己的比较器函数用于这个树集。 现在我使用descendingIterator()方法遍历此树集并更改元素。 那么这会更新实际树集以及使用我的自定义比较器排序的方式吗? 或者我是否需要删除元素并放回更新的元素?

您需要删除元素并将其添加回来。 通过将元素与其他元素进行比较,在插入元素时决定树中元素的位置。 如果更改对象以便与其他元素进行比较更改,则必须先删除元素,然后更改它,然后重新添加。

请注意,迭代时删除元素只能使用迭代器的remove方法。 如果没有获得ConcurrentModificationException,AFAIK,您将无法在迭代期间添加它。 因此,一旦迭代结束,将其存储在要重新添加到集合的元素列表中。

如果修改作为“键”一部分的对象的任何部分(由自定义比较器定义),则需要删除并重新插入树集的对象以“学习”有关更改的内容。 在迭代时你不应该这样做:一个好的方法是收集需要在一个循环中更改的项目,然后在另一个循环中修改并重新插入它们。

作为一般的经验法则,不建议“修改”添加到依赖于相等,哈希码等的Java容器的任何值类型,因为没有任何已知的标准容器执行自动平衡或调整以响应价值观的变化(这是有道理的)。

Set ,此规则对Map类型同样有效。 如果您在地图上迭代并在原地修改“密钥”,那么事情就会变得糟糕。 这就是为什么建议将不可变类型作为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