TreeSet class maintains a sorted set
of elements. This is cool, but it comes with a catch: elements are only sorted into the right places at insertion time,
but the sort order is never checked or updated later if element properties relevant for sorting change. So the only way
to update the sort order of a TreeSet is to temporarily remove a changed element and re-add it. This is tricky though,
because you cannot do it within a loop. Quote from
JDK docs for
Removes from the underlying collection the last element returned by this iterator (optional operation).
This method can be called only once per call to next().
The behavior of an iterator is unspecified if the underlying collection is modified while the iteration is
in progress in any way other than by calling this method.
I.e. only element removal is possible from inside a loop, and only when using an explicit
Iterator, not the
syntactically nicer form of:
It gets even more complicated if you want to update an element by removing and re-adding it. This cannot be done from
within a loop unless you create a copy of the set beforehand and loop over the copy so as not to disturb the iterator.
This is all very tedious, see also the corresponding
discussion on StackOverflow.com which sparked my idea of
UpdateableTreeSet. My user name there is also kriegaex, by the way.
UpdateableTreeSet extends the JDK class and provides a structured way for keeping the sort order up to date. All the
ugly, tedious details are hidden from you as a user, you just do something like this:
// Change the receiver's value} }
// Add elements to mySortedSet...
// Change or remove elements from inside a loop
// Trigger bulk update
updateMarked(); } }
As you can see, all the magic is done by three methods of
markForUpdate: mark an element as modified after you have changed its “sort key” property/properties.
markForRemoval: mark an element as obsolete so it gets removed later.
updateMarked: update/remove all marked elements in one batch operation.
While you can call
markFor* from within a loop safely, you should only call
updateMarked after you are done with
iterating over the set. That’s all there is to it, it is really straightforward.