Sunday, 20 March 2011

Collections that Support Iterator.remove()

The JSE Iterator specification states that the implementation of remove() is optional and that if unimplemented an UnsupportedOperationException is thrown. I suspect that this can, and does, lead to problems as best practice tells us that you should always used a collection interface as opposed to its concrete implementation... but that’s something I’ll demonstrate another day.

For now, I thought that it would be handy to know which iterators support remove() and which don’t.

package iterators.remove_supported;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Stack;
import java.util.TreeSet;
import java.util.Vector;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;

/**
* Test class designed to figure out which iterators support the optional remove() method and
* which don't.
*
*
@author Roger
*
*/
public class IteratorRemoveSupported {

 
private static Collection<Collection<String>> testCollections;

 
static {

   
testCollections = new ArrayList<Collection<String>>();
    testCollections.add
(new ArrayList<String>());
    testCollections.add
(new LinkedList<String>());
    testCollections.add
(new Vector<String>());
    testCollections.add
(new Stack<String>());
    testCollections.add
(new CopyOnWriteArrayList<String>());
    testCollections.add
(new TreeSet<String>());
    testCollections.add
(new LinkedHashSet<String>());
    testCollections.add
(new HashSet<String>());
    testCollections.add
(new CopyOnWriteArraySet<String>());
    testCollections.add
(new ConcurrentSkipListSet<String>());

    testCollections.add
(new ArrayBlockingQueue<String>(3));
    testCollections.add
(new ArrayDeque<String>());
    testCollections.add
(new ConcurrentLinkedQueue<String>());
    testCollections.add
(new HashSet<String>());
    testCollections.add
(new LinkedBlockingDeque<String>());

    testCollections.add
(new LinkedBlockingDeque<String>());
    testCollections.add
(new LinkedBlockingQueue<String>());

    testCollections.add
(new PriorityBlockingQueue<String>());
    testCollections.add
(new PriorityQueue<String>());
 
}

 
/**
   * Run the test, picking each
   *
   *
@param args
   */
 
public static void main(String[] args) {

   
System.out.println("Iterator remove() method Test Program.\n");

   
for (Collection<String> collection : testCollections) {
     
collection.add("Test String");
      testACollection
(collection);
   
}

   
System.out.println("\nIterator Test Program - End");
 
}

 
private static void testACollection(Collection<String> collection) {

   
System.out.print(collection.getClass().getSimpleName());
    Iterator<String> it = collection.iterator
();
   
try {
     
if (it.hasNext()) {
       
it.next(); // This has to be called BEFORE you can call remove()
       
it.remove(); // If not, you get an IllegalStateException
       
System.out.println(" - Supported");
     
} else {
       
System.out.println(" - Collection empty - Error");
     
}

    }
catch (Exception e) {
     
System.out.println(" - Unsupported");
   
}
  }

}
Running this code gives the following results showing which iterators support and which don’t support the Iterator.remove() method.

ArrayList - Supported
LinkedList - Supported
Vector - Supported
Stack - Supported
CopyOnWriteArrayList - Unsupported
TreeSet - Supported
LinkedHashSet - Supported
HashSet - Supported
CopyOnWriteArraySet - Unsupported
ConcurrentSkipListSet - Supported
ArrayBlockingQueue - Supported
ArrayDeque - Supported
ConcurrentLinkedQueue - Supported
HashSet - Supported
LinkedBlockingDeque - Supported
LinkedBlockingDeque - Supported
LinkedBlockingQueue - Supported
PriorityBlockingQueue - Supported
PriorityQueue - Supported

From these results you can see that most Iterator support remove, with the exception of CopyOnWriteArrayList and CopyOnWriteArraySet.

No comments: