3

I have this piece of code where I am traversing an ArrayList using an iterator, like:

Iterator iterator = list.iterator();
while (iterator.hasNext()) {
  Element element = iterator.next();
  iterator.remove();
  handle(element)
}

where ´handle(Element element)` goes like:

ListIterator iterator = list.listiterator();
iterator.add(element);

Now this gives a ConcurrentModificationException, since the iterator in the first method is not updated with the newly added element.

I have currently solved this using an CopyOnWriteArrayList, but these are very costly for performance. Is there a better way to fix this?

Thanks in advance!

(Note: the example doesn't make any sense, but was made to illustrate what I'm facing with)


I will try to explain why I am doing this:

  • I have a list of 'commands' in my main class that need to be executed

  • I have a while-loop (code 1 in the example) that iterates over these commands and execute them one-by-one, while removing them when executed from the list.

  • While executing a command, this command can in its turn add a new command to the list that is saved in my main class. (This is actually a bit more complicated: handling a command asks for a response from the client, which in its turn will responde with a command, and that one will get added to the saved list).

Ad Fundum
  • 665
  • 6
  • 22
  • 2
    Why are you doing this? That is, why are you trying to process the same list with two different types of iterator? – Makoto Apr 10 '16 at 00:33
  • Can you try and explain your real example, or a simplified version of it? – Paul Boddington Apr 10 '16 at 00:41
  • I have tried explaining what I am trying to do as best as possible (see edit). Sorry for the confusion and thanks for considering! – Ad Fundum Apr 10 '16 at 01:00
  • You shouldn't be modifiying a list within a loop that iterates over that list. You could first get it as an array, then do your removals from the list via the array's elements rather than directly via the list itself within an iterator. You can't affect the list by removing elements whilst you're iterating over it. – ManoDestra Apr 10 '16 at 01:03
  • 1
    How big does this list get? If it's just a few items then don't worry about performance so much. Worry if you can actually measure a problem. The copies are also not likely to be an issue if a lot of time is spent on other operations such as communicating with a client. – Alex Hall Apr 10 '16 at 01:03
  • Not sure if your situation allows it, but consider storing the commands to be added in a separate list and only adding them to the main list after the removals are complete. – Alex Hall Apr 10 '16 at 01:06
  • I am designing this for my thesis, so while my example implementation doesn't get that big, I should take performance into consideration, hence the question. But good point on the client-communication, that probably takes more performance in comparison. Only adding commands after the previous ones are removed comes with a lot of communication/connection setup overhead, so that isn't really possible. But thanks a lot for your input! – Ad Fundum Apr 10 '16 at 01:21
  • This looks like a little workflow engine to me. If this is the case, you should find another way to model the flow, i.e. instead of storing all commands in a list, you could let each command specify which the next command is. To execute the flow, then execute the first command, ask it which the next command is, execute that one, etc, until there's no next command. – fps Apr 10 '16 at 01:30

1 Answers1

5

Given the requirements as stated, the simple solution is to use a Queue (javadoc) rather than a List.

I have a list of 'commands' in my main class that need to be executed

A Queue can represent a sequence of commands.

I have a while-loop (code 1 in the example) that iterates over these commands and execute them one-by-one, while removing them when executed from the list.

The equivalent for a Queue is to repeatedly call remove() or poll() or the like to get and remove the first command from the Queue. You do this repeatedly until the Queue is empty.

Note that this does not involve an Iterator.

While executing a command, this command can in its turn add a new command to the list that is saved in my main class.

That can be done by calling add() or offer() to add a command to the Queue.


Note that there are lots of different implementations of Queue with different properties:

  • queues with finite or infinite sizes
  • queues that block or don't block
  • simple FIFO queues versus LIFO queues or priority queues
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • I was unaware that you could iterate safely over a Queue while using `poll()`. This is indeed exactly what I was looking for. Thanks! For those wondering: I have implemented my queue as a `PriorityBlockingQueue` , since my commands are being executed in different threads and can modify the queue concurrently (thus a `PriorityQueue` would not suffice). – Ad Fundum Apr 10 '16 at 03:05