commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From scolebou...@btopenworld.com
Subject RE: [collections]SingleElementCollection (was Questions....)
Date Thu, 21 Aug 2003 10:23:03 GMT
This is already available on the java.util.Collections class.

The purpose of SingletonIterator/SingletonListIterator is to enable you to create the iterator
without needing to create an intermediate object such as SingletonCollection.

They are typically used for performance, see the Jaxen library for example.

Stephen

>  from:    "Hope, Matthew" <Matthew.Hope@capitalone.com>
> inlined as attachment was stripped...
> 
> import java.util.*;
> 
> /**
>  * Quick and simple implementation of a single element collection. The
> collection
>  * starts with one entry and always keeps it that way, therefore
> modification
>  * operations will result in UnsupportedOperationException. The class is
>  * unsynchronized. The collection can hold null and will treat it in a
> similar
>  * fashion to List. Details of this are by each method.
>  *
>  * @author   Matt Hope
>  */
> public class SingleElementCollection implements Collection
> {
> 
>     private class SingleIterator implements Iterator
>     {
>         private boolean nextHasBeenCalled = false;
> 
>         /**
>          * contract of Iterator#hasNext() maintained
>          *
>          * @return
>          */
>         public boolean hasNext()
>         {
>             if (nextHasBeenCalled) {
>                 return false;
>             }
>             return true;
>         }
> 
>         /**
>          * contract of Iterator#next() maintained
>          *
>          * @return
>          */
>         public Object next()
>         {
>             if (nextHasBeenCalled) {
>                 throw new NoSuchElementException("only one entry defined");
>             } else {
>                 nextHasBeenCalled = true;
>                 return theElement;
>             }
>         }
> 
>         /**
>          * This will throw an UnsupportedOperationException since the
> underlying
>          * Colelction does not support removal
>          */
>         public void remove()
>         {
>             throw new UnsupportedOperationException("SingleElementCollection
> does not supprt the removal of elements");
>         }
> 
>     }
> 
>     private Object theElement;
> 
>     /**
>      * Constructor for the SingleElementCollection object
>      *
>      * @param o  the Object to use in the collection. null is allowed
>      */
>     public SingleElementCollection(Object o)
>     {
>         theElement = o;
>     }
> 
>     /**
>      * This will always be 1
>      *
>      * @return
>      */
>     public int size()
>     {
>         return 1;
>     }
> 
>     /**
>      * this will always be false
>      *
>      * @return   The empty
>      */
>     public boolean isEmpty()
>     {
>         return false;
>     }
> 
>     /**
>      * True iff (o==null ? theElement==null : o.equals(e)) as for
>      * List#contains()
>      *
>      * @return
>      * @param o  the object for comparison
>      */
>     public boolean contains(Object o)
>     {
>         return o == null ? theElement == null : o.equals(theElement);
>     }
> 
>     /**
>      * returns an Iterator which will return the element in the collection.
> It
>      * does not support removal
>      *
>      * @return
>      */
>     public Iterator iterator()
>     {
>         return new SingleElementCollection.SingleIterator();
>     }
> 
>     /**
>      * converts the collection to an Object array of length 1
>      *
>      * @return
>      */
>     public Object[] toArray()
>     {
>         return new Object[]{theElement};
>     }
> 
>     /**
>      * as for Collection#toArray(Object[])
>      *
>      * @return
>      * @param a
>      */
>     public Object[] toArray(Object[] a)
>     {
>         if (a.length < 1) {
>             a = (Object[]) java.lang.reflect.Array.newInstance(
>                     a.getClass().getComponentType(), 1);
>         }
> 
>         System.arraycopy(toArray(), 0, a, 0, 1);
> 
>         if (a.length > 1) {
>             a[1] = null;
>         }
> 
>         return a;
>     }
> 
>     /**
>      * modification not allowed - UnsupportedOperationException will be
> thrown
>      *
>      * @return
>      * @param o
>      */
>     public boolean add(Object o)
>     {
>         throw new java.lang.UnsupportedOperationException("Method add() not
> supported - collection content is immutable");
>     }
> 
>     /**
>      * modification not allowed - UnsupportedOperationException will be
> thrown
>      *
>      * @return
>      * @param o
>      */
>     public boolean remove(Object o)
>     {
>         throw new java.lang.UnsupportedOperationException("Method remove()
> not supported - collection content is immutable");
>     }
> 
>     /**
>      * as for Collection#containsAll(c)
>      *
>      * @return
>      * @param c
>      */
>     public boolean containsAll(Collection c)
>     {
>         if (c.size() != 1) {
>             return false;
>         } else {
>             return c.contains(theElement);
>         }
>     }
> 
>     /**
>      * modification not allowed - UnsupportedOperationException will be
> thrown
>      *
>      * @return
>      * @param c  The All to be added
>      */
>     public boolean addAll(Collection c)
>     {
>         throw new java.lang.UnsupportedOperationException("Method addAll()
> not supported - collection content is immutable");
>     }
> 
>     /**
>      * modification not allowed - UnsupportedOperationException will be
> thrown
>      *
>      * @return
>      * @param c
>      */
>     public boolean removeAll(Collection c)
>     {
>         throw new java.lang.UnsupportedOperationException("Method addAll()
> not supported - collection content is immutable");
>     }
> 
>     /**
>      * Makes no effort to check if the operation would do nothing (and hence
> not
>      * violate the immutable invariant. It just throws
>      * UnsupportedOperationException
>      *
>      * @return
>      * @param c
>      */
>     public boolean retainAll(Collection c)
>     {
>         throw new java.lang.UnsupportedOperationException("Method
> retainAll() not supported - collection content is immutable");
>     }
> 
>     /**
>      * modification not allowed - UnsupportedOperationException will be
> thrown
>      */
>     public void clear()
>     {
>         throw new java.lang.UnsupportedOperationException("Method clear()
> not supported - collection content is immutable");
>     }
> 
>     /**
>      * returns true if the Object is an instance of SingleElementCollection
>      * which contains an element equal to this one.
>      *
>      * @return
>      * @param o
>      */
>     public boolean equals(Object o)
>     {
>         if (o instanceof SingleElementCollection) {
>             SingleElementCollection other = (SingleElementCollection) o;
>             return containsAll(other);
>         }
>         return false;
>     }
> 
>     /**
>      * returns the hashcode of the element or zero is null
>      *
>      * @return
>      */
>     public int hashCode()
>     {
>         return theElement == null ? 0 : theElement.hashCode();
>     }
> }
> 
> import java.util.*;
> import junit.framework.*;
> 
> /**
>  * Quick and simple implementation of an immutable single element
> colection.<br>
>  * The collection starts with one entry and always keeps it that way,
> therefore
>  * certain operations will result in UnsupportedOperationException. <br>
>  * The collection is unsynchronized.<br>
>  * The collection can hold null and will treat it in a similar fashion to
> List.
>  * Details of this are by each method.
>  *
>  * @author   Matt Hope
>  */
> public class TestSingleElementCollection extends TestCase
> {
>     private final Object TEST_ELEMENT = new Object();
> 
>     public TestSingleElementCollection(String name)
>     {
>         super(name);
>     }
> 
>     public void testSize()
>     {
>         assertEquals(1, new SingleElementCollection(TEST_ELEMENT).size());
>         assertEquals(1, new SingleElementCollection(null).size());
>     }
> 
>     public void testIsEmpty()
>     {
>         assertFalse(new SingleElementCollection(TEST_ELEMENT).isEmpty());
>         assertFalse(new SingleElementCollection(null).isEmpty());
>     }
> 
>     public void testContains()
>     {
>         assertTrue(new SingleElementCollection(null).contains(null));
>         assertTrue(new
> SingleElementCollection(TEST_ELEMENT).contains(TEST_ELEMENT));
>         assertTrue(new SingleElementCollection(new Integer(1)).contains(new
> Integer(1)));
>         assertFalse(new
> SingleElementCollection(null).contains(TEST_ELEMENT));
>         assertFalse(new
> SingleElementCollection(TEST_ELEMENT).contains(null));
>     }
> 
>     public void testIterator()
>     {
>         assertTrue(new
> SingleElementCollection(TEST_ELEMENT).iterator().hasNext());
>         assertTrue(new SingleElementCollection(null).iterator().hasNext());
>         assertEquals(TEST_ELEMENT, new
> SingleElementCollection(TEST_ELEMENT).iterator().next());
>         assertEquals(null, new
> SingleElementCollection(null).iterator().next());
>         Iterator iter = new
> SingleElementCollection(TEST_ELEMENT).iterator();
>         iter.next();
>         assertFalse(iter.hasNext());
>         try {
>             iter.next();
>             fail("should have thrown NoSuchElementException");
>         } catch (NoSuchElementException e) {
>             // pass
>         }
>     }
> 
>     public void testToArray()
>     {
>         assertNull(new SingleElementCollection(null).toArray()[0]);
>         assertEquals(1, new SingleElementCollection(null).toArray().length);
>         assertEquals(TEST_ELEMENT, new
> SingleElementCollection(TEST_ELEMENT).toArray()[0]);
>         assertEquals(1, new
> SingleElementCollection(TEST_ELEMENT).toArray().length);
>     }
> 
>     public void testToArray_withParameter()
>     {
>         assertNull(new SingleElementCollection(null).toArray(new
> Object[0])[0]);
>         assertEquals(1, new SingleElementCollection(null).toArray(new
> Object[0]).length);
>         assertEquals(TEST_ELEMENT, new
> SingleElementCollection(TEST_ELEMENT).toArray(new Object[0])[0]);
>         assertEquals(1, new
> SingleElementCollection(TEST_ELEMENT).toArray(new Object[0]).length);
>         assertEquals(TEST_ELEMENT, new
> SingleElementCollection(TEST_ELEMENT).toArray(new Object[2])[0]);
>         assertNull(new SingleElementCollection(TEST_ELEMENT).toArray(new
> Object[2])[1]);
>         Object[] three = new Object[]{"nought", "one", "two"};
>         assertEquals(TEST_ELEMENT, new
> SingleElementCollection(TEST_ELEMENT).toArray(three)[0]);
>         assertNull(new
> SingleElementCollection(TEST_ELEMENT).toArray(three)[1]);
>         assertEquals(three[2], new
> SingleElementCollection(TEST_ELEMENT).toArray(three)[2]);
> 
>     }
> 
>     public void testAdd()
>     {
>         try {
>             new SingleElementCollection(TEST_ELEMENT).add("foo");
>             fail("should have thrown UnsupportedOperationException");
>         } catch (UnsupportedOperationException e) {
>             //pass
>         }
>     }
> 
>     public void testRemove()
>     {
>         try {
>             new SingleElementCollection(TEST_ELEMENT).remove(TEST_ELEMENT);
>             fail("should have thrown UnsupportedOperationException");
>         } catch (UnsupportedOperationException e) {
>             //pass
>         }
>     }
> 
>     public void testContainsAll_Set()
>     {
>         Set equalSet = new HashSet();
>         equalSet.add(TEST_ELEMENT);
>         Set emptySet = new HashSet();
>         Set biggerSet = new HashSet();
>         biggerSet.add(TEST_ELEMENT);
>         biggerSet.add("foo");
>         assertFalse(new
> SingleElementCollection(TEST_ELEMENT).containsAll(emptySet));
>         assertTrue(new
> SingleElementCollection(TEST_ELEMENT).containsAll(equalSet));
>         assertFalse(new
> SingleElementCollection(TEST_ELEMENT).containsAll(biggerSet));
>     }
> 
>     public void testContainsAll_List()
>     {
>         List equalList = new ArrayList();
>         equalList.add(TEST_ELEMENT);
>         List emptyList = new ArrayList();
>         List biggerList = new ArrayList();
>         biggerList.add(TEST_ELEMENT);
>         biggerList.add("foo");
>         assertFalse(new
> SingleElementCollection(TEST_ELEMENT).containsAll(emptyList));
>         assertTrue(new
> SingleElementCollection(TEST_ELEMENT).containsAll(equalList));
>         assertFalse(new
> SingleElementCollection(TEST_ELEMENT).containsAll(biggerList));
>     }
> 
>     public void testAddAll()
>     {
>         try {
>             new SingleElementCollection(TEST_ELEMENT).addAll(new HashSet());
>             fail("should have thrown UnsupportedOperationException");
>         } catch (UnsupportedOperationException e) {
>             //pass
>         }
>     }
> 
>     public void testRemoveAll()
>     {
>         try {
>             new SingleElementCollection(TEST_ELEMENT).removeAll(new
> HashSet());
>             fail("should have thrown UnsupportedOperationException");
>         } catch (UnsupportedOperationException e) {
>             //pass
>         }
>     }
> 
>     public void testRetainAll()
>     {
>         try {
>             new SingleElementCollection(TEST_ELEMENT).retainAll(new
> HashSet());
>             fail("should have thrown UnsupportedOperationException");
>         } catch (UnsupportedOperationException e) {
>             //pass
>         }
>     }
> 
>     public void testClear()
>     {
>         try {
>             new SingleElementCollection(TEST_ELEMENT).clear();
>             fail("should have thrown UnsupportedOperationException");
>         } catch (UnsupportedOperationException e) {
>             //pass
>         }
>     }
> 
>     public void testEquals()
>     {
>         SingleElementCollection same = new
> SingleElementCollection(TEST_ELEMENT);
>         Set sameSet = new HashSet();
>         sameSet.add(TEST_ELEMENT);
>         assertEquals(same, same);
>         assertEquals(same, new SingleElementCollection(TEST_ELEMENT));
>         assertEquals(new SingleElementCollection(null), new
> SingleElementCollection(null));
>         assertFalse(new
> SingleElementCollection(TEST_ELEMENT).equals(sameSet));
>         assertFalse(new SingleElementCollection(TEST_ELEMENT).equals(new
> SingleElementCollection(null)));
>         assertFalse(new SingleElementCollection(null).equals(new
> SingleElementCollection(TEST_ELEMENT)));
>         assertFalse(new SingleElementCollection(new Integer(1)).equals(new
> SingleElementCollection(new Integer(2))));
>         assertEquals(new SingleElementCollection(new Integer(1)), new
> SingleElementCollection(new Integer(1)));
>     }
> 
>     public void testHashCode()
>     {
>         assertEquals(TEST_ELEMENT.hashCode(), new
> SingleElementCollection(TEST_ELEMENT).hashCode());
>         assertEquals(0, new SingleElementCollection(null).hashCode());
>     }
> }
> 
> 
> 
> > -----Original Message-----
> > From: Hope, Matthew 
> > Sent: 20 August 2003 15:16
> > To: 'Jakarta Commons Developers List'
> > Subject: RE: [collections] Questions....
> > 
> > 
> > I knocked this up - javadocs are crap but is this the sort of 
> > thing you were
> > thinking of?
> > 
> > a mutable version is not too hard either.
> > 
> > Matt
> > 
> > > -----Original Message-----
> > > From: Hope, Matthew 
> > > Sent: 20 August 2003 13:18
> > > To: 'Jakarta Commons Developers List'
> > > Subject: RE: [collections] Questions....
> > > 
> > > 
> > > > -----Original Message-----
> > > > From: Takuya Murata [mailto:takusi@manjiro.net] 
> > > > Sent: 20 August 2003 12:14
> > > > To: Jakarta Commons Developers List
> > > > Subject: Re: [collections] Questions....
> > > > 
> > > > class Singleton implements List {
> > > > }
> > > > 
> > > > ResetableIterator i = new Singleton ("hello, world").iterator ();
> > > > ListIterator li = new Singleton ("hello, world").listIterator ();
> > > > ListIterator li = new Singleton ("hello, 
> > world").listIterator (10);
> > > 
> > > I personally have a problem with the use of the class name 
> > Singleton.
> > > Singleton is a well known pattern for only having one 
> > > instance of an Object
> > > in an environment, this class does not achive this. I would 
> > > think a name
> > > likeSingleEntryIterator/TrivialIterator/MonoIterator or some 
> > > such would be a
> > > better descriptive name.
> > >  
> > > > To me, this solution sounds good. There is no tricky 
> > choice whether 
> > > > SingletonIterator or SingletonListIterator. And we can 
> > avoid a big 
> > > > xxxUtil classes instead of small objects and classes, resembling 
> > > > traditional imperative languages such as C.
> > > 
> > > The whole point of Iterator is that it is collection type 
> > > independent - no
> > > matter what data structure in place iterator should supply 
> > > you with every
> > > Object in it - ordering appropriately if required.
> > > 
> > > If it is being used for code expecting a ListIterator I would 
> > > say that that
> > > code needs to be made more agnostic of the underlying 
> > > implementation (given
> > > that you would be using this quick method of supplying just 
> > > the one value).
> > > Though in fairness making it return a ListItertor (but keep 
> > > the signature to
> > > Iterator) would be no big deal.
> > > 
> > > > I am not sure if it is valid with the contract of interfaces to 
> > > > implement both Set and List because ListIterator doesn't 
> > make sense 
> > > > with listIterator but it doesn't look elegant to have two 
> > > > SingletonList 
> > > > and SingletonSet classes.
> > > 
> > > Perhaps it would be better to create a class 
> > > SingleEntryCollection which
> > > extends collection and implements the iterator method as well 
> > > as the rest.
> > > The cost is one additional object for your siple use case but 
> > > it may provide
> > > a clearer picture of what is being performed...If the 
> > > Collection itself
> > > implements Iterator then it can just return itself in 
> > response to the
> > > method. I can't see a name clash except remove() and they are 
> > > different
> > > signatures in both return type and parameters...
> > > 
> > > If I'm missing the point of what you're trying to do here 
> > let me know
> > > 
> > > Matt
> > >  
> > > **************************************************************
> > > ************
> > > The information transmitted herewith is sensitive information 
> > > intended only
> > > for use by the individual or entity to which it is addressed. 
> > > If the reader
> > > of this message is not the intended recipient, you are hereby 
> > > notified that
> > > any review, retransmission, dissemination, distribution, 
> > > copying or other
> > > use of, or taking of any action in reliance upon this information is
> > > strictly prohibited. If you have received this 
> > communication in error,
> > > please contact the sender and delete the material from your 
> > computer.
> > > 
> > > 
> > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> > > For additional commands, e-mail: commons-dev-help@jakarta.apache.org
> > > 
> >  
> > **************************************************************
> > ************
> > The information transmitted herewith is sensitive information 
> > intended only
> > for use by the individual or entity to which it is addressed. 
> > If the reader
> > of this message is not the intended recipient, you are hereby 
> > notified that
> > any review, retransmission, dissemination, distribution, 
> > copying or other
> > use of, or taking of any action in reliance upon this information is
> > strictly prohibited. If you have received this communication in error,
> > please contact the sender and delete the material from your computer.
> >     
> > 
> > 
> > 
>  
> **************************************************************************
> The information transmitted herewith is sensitive information intended only
> for use by the individual or entity to which it is addressed. If the reader
> of this message is not the intended recipient, you are hereby notified that
> any review, retransmission, dissemination, distribution, copying or other
> use of, or taking of any action in reliance upon this information is
> strictly prohibited. If you have received this communication in error,
> please contact the sender and delete the material from your computer.
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
> 


Mime
View raw message