Modified Concurrent Exception

What is the preferred way to iterate of a collection to modify its elements?

I have only found two solutions:

  1. Create a new collection, then select addAll(). After that iterate the new collection
  2. Use org.apache.commons.collections.list.CursorableLinkedList
    This allows modifications of the list while iterating.

Are there any other solutions? And which is the most preferable?
Because I guess if all work its mainly a performance question.

When you iterate over a Collection with an Iterator, and remove elements, you should get a “Modified Concurrent Exception” as the title suggests.

To answer your question: it depends.

Variables:

  • type of collection
  • size of collection
  • usage of collection

[quote]When you iterate over a Collection with an Iterator, and remove elements, you should get a “Modified Concurrent Exception” as the title suggests.
[/quote]
I understand, but I need to loop thru some objects to perform cleanup. As an object cleans up it removes itself from its parent causing the exception.

[quote]Variables:

  • type of collection
  • size of collection
  • usage of collection
    [/quote]
    My most common collections are:
    ArrayList or HashSet with approximately 1-20 elements. There is a fair deal of insert and removal, but getting them is most common ofc.

Have you tried the ‘Bag’ collection?

It might be exactly what you need.


import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Comparator;

public class Bag<E>
{
   private final E[] array;
   private int       count;

   public Bag(E e, int capacity)
   {
      this.array = (E[]) Array.newInstance(e.getClass(), capacity);
   }

   public final int count()
   {
      return count;
   }

   public final void put(E e)
   {
      // no checks... don't grow, just deal with the current capacity
      array[count++] = e;
   }

   public final E swap(int index, E e)
   {
      E org = array[index];
      array[index] = e;
      return org;
   }

   public final E grab(int index)
   {
      return array[index];
   }

   public final int search(E e)
   {
      for (int i = 0; i < count; i++)
         if (array[i] == e)
            return i;
      return -1;
   }

   public final void dispose(int index)
   {
      array[index] = array[--count];
      array[count + 1] = null;
   }

   public final void sort(Comparator<E> c)
   {
      Arrays.sort(array, 0, count, c);
   }
}

I don’t think I can use it, as I don’t know the capacity.

To answer your original question then:

ArraysLists are extremely quick to copy around, so that’s probably the way to go, don’t use iterators though, direct access with get( i ) and remove( i ) is much faster. Enhanced-for is evil.

HashMaps/Sets are fairly expensive to construct and fill, lookup will only be faster than ArrayLists on fairly big collections (~64+ elements or so) especially when the internals are building linkedlists (due to overlapping hashes)

If you just want to get rid of the concurrent modification exception you can also use Iterator#remove.

Collection c;
Iterator i = c.iterator();
while(i.hasNext()) {
  Object o = i.next();
  if (/*should remove o*/) {
    i.remove();
  }
}

Ok, taking all advice into consideration I ended up with this.
What do you think?

public void reset(){
	Object actorA[] = actors.toArray();
	for(int i=0;i<actorA.length;i++){
		final Actor a = (Actor) actorA[i];	
		a.unload();
	}
}

How much slower are we talking about? I use iterators all over my code because they’re cleaner, and because I actually iterate through all elements.

factor 3, overhead.

For LinkedLists, you definitely want Iterators though.

I usually do this when I want to delete elemets from a List:

public void reset(){
	for (int i=actors.size()-1;i>=0;i--){
                if (/*elemnt should be deleted*/) {
                      actors.remove(i);
                }
	}
}