Tuesday, 22 March 2011

Collections that support the remove() method

The JSE Collection specification states that the implementation of remove() is optional and that if unimplemented an UnsupportedOperationException is thrown. So, I thought that it would be handy to know which collection classes support remove() and which don’t. Using the following code I get some interesting results...

package collections.remove_supported;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
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 collection classes support the optional remove()
* method and which don't.
*/
public class CollectionsRemoveSupported {

 
private static final String TEST_STRING = "Hello World";

 
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 collection type in turn
   *
   *
@param args
   *            Not Used
   */
 
public static void main(String[] args) {

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

   
for (Collection<String> collection : testCollections) {
     
testACollection(collection);
   
}

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

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

   
try {
     
System.out.print(collection.getClass().getSimpleName());

      collection.add
(TEST_STRING);
      collection.remove
(TEST_STRING);
      System.out.println
(" - Supported");

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

}

Running this code demonstrates that all the Collection classes in our test list support remove().

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

This is interesting as whilst all the collections classes support Collection.remove(), not all collection iterators support Iterator.remove(). This means that when writing collection utilities that deal with unknown collection implementation types via interfaces, your code will be more stable if you stick to using Collection.remove() and avoid Iterator.remove().

No comments: