Re: iterators
On Wed, 5 Aug 2009, Daniel Pitts wrote:
Eric Sosman wrote:
Daniel Pitts wrote:
[...]
What I would *love* is an iterator that can be made smart enough to not
throw ConcurrentModificationException if the modification can be proven to
be non-conflicting (such as appending to a list, or removing a node from a
linked-list, which is not any node being pointed to by the iterator.)
Can you give some examples of situations where you've wished you
had such a thing?
I have a simulation involving robots which can shoot at each other. Once a
robot is destroyed, it is removed from the list. At the time that damage is
dealt, I am already iterating through that list.
This means that I must go through the list afterward and remove the dead
robots, instead of removing them as they die.
This is a simplified example. The list itself may contain other objects (such
as missiles, mines, etc...) each of which may cease to exist and/or inflict
damage at any time.
I had exactly that problem many years ago, only it was spaceships instead
of robots.
How about something like:
Collection<Thing> things; // robots, missiles, mines, etc
void carryOutATurn() {
List thingsToDo = new LinkedList(things);
while (!thingsToDo.isEmpty()) {
Thing next = thingsToDo.remove(0);
Collection<Thing> casualties = next.takeTurn();
if (!casualties.isEmpty()) {
things.removeAll(casualties);
thingsToDo.removeAll(casualties);
}
}
}
This does involve creating and throwing away a linked list of everything
in the universe on every turn, and potentially a lot of little casualty
lists too - although these can be emptySet or singleton sets from
Collections, which are very cheap.
It would be straightforward to extend this to handle new things (a
newly-fired missile, etc) as well.
An alternative to the casualty list would be to create and pass in a
little callback object for deleting things:
class Undertaker {
public void kill(Thing t) {
things.remove(t);
thingsToDo.remove(t);
}
}
tom
--
If it ain't broke, open it up and see what makes it so bloody special.