commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Hope, Matthew" <Matthew.H...@capitalone.com>
Subject RE: [collections]SingleElementCollection (was Questions....)
Date Thu, 21 Aug 2003 11:11:08 GMT
doh! should have looked in there first, cheers

Matt

> -----Original Message-----
> From: scolebourne@btopenworld.com 
> [mailto:scolebourne@btopenworld.com] 
> Sent: 21 August 2003 11:23
> To: commons-dev@jakarta.apache.org
> Subject: RE: [collections]SingleElementCollection (was Questions....)
> 
> 
> 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
> > 
> 
> 
> ---------------------------------------------------------------------
> 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.

Mime
View raw message