This is a follow up question to ‘Is there a basic Java Set implementation that does not permit nulls?‘. (thank you to all of those who helped with the answer)
It seems that the way to do this, since Sun didn’t provide something simple like this OOTB, is with a wrapper / proxy. This seems nearly straight forward. What I am wondering is what are the pros/cons of the following two approaches of adding a collection, or is there another better approach?
Approach #1
public boolean addAll( Collection<? extends E> c) { if ( null == c ) { throw new NullPointerException( 'c cannot be null' ); } /* * This seems like a terrible abuse of exceptions when * all I want to do is check the set for a null. * * However, simply running through each element of the * Collection may provide much worse performance for large * collections. And according to the Collection API, the * contains method may throw NullPointerExceptions if the * collection implementation does not allow null elements. */ boolean collectionContainsNull = false; try { collectionContainsNull = c.contains(null); } catch (NullPointerException safeToIgnore) { /* Safe to ignore since we do not want nulls */ } if (collectionContainsNull) { throw new NullPointerException('c cannot contain null elements'); } this.wrapperSet.addAll(c); }
Approach #2
public boolean addAll( Collection<? extends E> c) { if ( null == c ) { throw new NullPointerException( 'c cannot be null' ); } E[] a = ( E[] )c.toArray(); /* * We have to iterate through the entire collection to check for * a null. This won't take advantage of any optimizations that * c.contains may be using. * * We don't call add(e) here because if we hit a null midway through * we would violate the condition that the set remains unchanged * on error. */ for ( E e : a ) { if (null == e) { throw new NullPointerException('c cannot contain nulls'); } } this.wrapperSet.addAll(a); }
Thanks in advance!
The second approach is better. Never hide exceptions – you are relying on the assumption that c.contains(null) only throws a NullPointerException in the case that there is a null in the collection. However if the NullPointeException is thrown because of a problem with an equals method you will have a bug in your code – and you will have hidden it.
Edit:
From the JavaDoc for contains, NullPointerException is thrown – if the specified element is null and this collection does not permit null elements (optional).
Given that it is an optional method you may wind up with an UnsupportedOperationException being thrown instead of the NullPointerExcepion (in addition to hiding the an error in equals).