简体   繁体   中英

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. Now I am traversing this tree set using descendingIterator() method and changing the elements. 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. And you won't be able to add it during the iteration without getting a 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).

Along with Set , this rule is equally valid for Map types. 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:

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]]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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