You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by sc...@apache.org on 2003/09/20 18:57:47 UTC

cvs commit: jakarta-commons/collections/src/test/org/apache/commons/collections/decorators TestOrderedSet.java

scolebourne    2003/09/20 09:57:47

  Modified:    collections/src/java/org/apache/commons/collections/decorators
                        OrderedSet.java
               collections/src/test/org/apache/commons/collections/decorators
                        TestOrderedSet.java
  Log:
  Enhance OrderedSet to support List like functions
  
  Revision  Changes    Path
  1.2       +97 -7     jakarta-commons/collections/src/java/org/apache/commons/collections/decorators/OrderedSet.java
  
  Index: OrderedSet.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/decorators/OrderedSet.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- OrderedSet.java	9 Sep 2003 22:28:35 -0000	1.1
  +++ OrderedSet.java	20 Sep 2003 16:57:47 -0000	1.2
  @@ -59,6 +59,8 @@
   
   import java.util.ArrayList;
   import java.util.Collection;
  +import java.util.Collections;
  +import java.util.HashSet;
   import java.util.Iterator;
   import java.util.List;
   import java.util.Set;
  @@ -67,10 +69,17 @@
    * Decorates a <code>Set</code> to ensure that the order of addition
    * is retained and used by the iterator.
    * <p>
  - * If an object is added to the Set for a second time, it will remain in the
  + * If an object is added to the set for a second time, it will remain in the
    * original position in the iteration.
  + * The order can be observed from the set via the iterator or toArray methods.
    * <p>
  - * The order can be observed via the iterator or toArray methods.
  + * The OrderedSet also has various useful direct methods. These include many
  + * from <code>List</code>, such as <code>get(int)</code>, <code>remove(int)</code>
  + * and <code>indexOf(int)</code>. An unmodifiable <code>List</code> view of 
  + * the set can be obtained via <code>asList()</code>.
  + * <p>
  + * This class cannot implement the <code>List</code> interface directly as
  + * various interface methods (notably equals/hashCode) are incompatable with a set.
    *
    * @since Commons Collections 3.0
    * @version $Revision$ $Date$
  @@ -81,19 +90,36 @@
   public class OrderedSet extends AbstractSetDecorator implements Set {
   
       /** Internal list to hold the sequence of objects */
  -    protected final List setOrder = new ArrayList();
  +    protected final List setOrder;
   
       /**
        * Factory method to create an ordered set.
  +     * <p>
  +     * An <code>ArrayList</code> is used to retain order.
        * 
        * @param set  the set to decorate, must not be null
        * @throws IllegalArgumentException if set is null
        */
  -    public static Set decorate(Set set) {
  +    public static OrderedSet decorate(Set set) {
           return new OrderedSet(set);
       }
   
       /**
  +     * Factory method to create an ordered set using the supplied list to retain order.
  +     * <p>
  +     * A <code>HashSet</code> is used for the set behaviour.
  +     * 
  +     * @param list  the list to decorate, must not be null
  +     * @throws IllegalArgumentException if set is null
  +     */
  +    public static OrderedSet decorate(List list) {
  +        Set set = new HashSet(list);
  +        list.retainAll(set);
  +        
  +        return new OrderedSet(set, list);
  +    }
  +
  +    /**
        * Constructor that wraps (not copies).
        * 
        * @param set  the set to decorate, must not be null
  @@ -101,7 +127,34 @@
        */
       protected OrderedSet(Set set) {
           super(set);
  -        setOrder.addAll(set);
  +        setOrder = new ArrayList(set);
  +    }
  +
  +    /**
  +     * Constructor that wraps (not copies) the Set and specifies the list to use.
  +     * <p>
  +     * The set and list must both be correctly initialised to the same elements.
  +     * 
  +     * @param set  the set to decorate, must not be null
  +     * @param list  the list to decorate, must not be null
  +     * @throws IllegalArgumentException if set or list is null
  +     */
  +    protected OrderedSet(Set set, List list) {
  +        super(set);
  +        if (list == null) {
  +            throw new IllegalArgumentException("List must not be null");
  +        }
  +        setOrder = list;
  +    }
  +
  +    //-----------------------------------------------------------------------
  +    /**
  +     * Gets an unmodifiable view of the order of the Set.
  +     * 
  +     * @return an unmodifiable list view
  +     */
  +    public List asList() {
  +        return Collections.unmodifiableList(setOrder);
       }
   
       //-----------------------------------------------------------------------
  @@ -175,6 +228,43 @@
           return setOrder.toArray(a);
       }
   
  +    //-----------------------------------------------------------------------
  +    public Object get(int index) {
  +        return setOrder.get(index);
  +    }
  +
  +    public int indexOf(Object object) {
  +        return setOrder.indexOf(object);
  +    }
  +
  +    public void add(int index, Object object) {
  +        if (contains(object) == false) {
  +            collection.add(object);
  +            setOrder.add(index, object);
  +        }
  +    }
  +
  +    public boolean addAll(int index, Collection coll) {
  +        boolean changed = false;
  +        for (Iterator it = coll.iterator(); it.hasNext();) {
  +            Object object = (Object) it.next();
  +            if (contains(object) == false) {
  +                collection.add(object);
  +                setOrder.add(index, object);
  +                index++;
  +                changed = true;
  +            }
  +        }
  +        return changed;
  +    }
  +
  +    public Object remove(int index) {
  +        Object obj = setOrder.remove(index);
  +        remove(obj);
  +        return obj;
  +    }
  +
  +    //-----------------------------------------------------------------------
       /**
        * Internal iterator handle remove.
        */
  
  
  
  1.2       +76 -2     jakarta-commons/collections/src/test/org/apache/commons/collections/decorators/TestOrderedSet.java
  
  Index: TestOrderedSet.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/collections/src/test/org/apache/commons/collections/decorators/TestOrderedSet.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TestOrderedSet.java	9 Sep 2003 22:28:36 -0000	1.1
  +++ TestOrderedSet.java	20 Sep 2003 16:57:47 -0000	1.2
  @@ -57,8 +57,10 @@
    */
   package org.apache.commons.collections.decorators;
   
  +import java.util.ArrayList;
   import java.util.HashSet;
   import java.util.Iterator;
  +import java.util.List;
   import java.util.Set;
   
   import junit.framework.Test;
  @@ -134,6 +136,78 @@
           for (int i = 0; i < 10; i += 2) {
               assertEquals("Sequence is wrong", Integer.toString(i), it.next());
           }
  +    }
  +    
  +    private static final Integer ZERO = new Integer(0);
  +    private static final Integer ONE = new Integer(1);
  +    private static final Integer TWO = new Integer(2);
  +    private static final Integer THREE = new Integer(3);
  +    
  +    public void testListAddRemove() {
  +        OrderedSet set = (OrderedSet) makeEmptySet();
  +        List view = set.asList();
  +        set.add(ZERO);
  +        set.add(ONE);
  +        set.add(TWO);
  +        
  +        assertEquals(3, set.size());
  +        assertSame(ZERO, set.get(0));
  +        assertSame(ONE, set.get(1));
  +        assertSame(TWO, set.get(2));
  +        assertEquals(3, view.size());
  +        assertSame(ZERO, view.get(0));
  +        assertSame(ONE, view.get(1));
  +        assertSame(TWO, view.get(2));
  +        
  +        assertEquals(0, set.indexOf(ZERO));
  +        assertEquals(1, set.indexOf(ONE));
  +        assertEquals(2, set.indexOf(TWO));
  +        
  +        set.remove(1);
  +        assertEquals(2, set.size());
  +        assertSame(ZERO, set.get(0));
  +        assertSame(TWO, set.get(1));
  +        assertEquals(2, view.size());
  +        assertSame(ZERO, view.get(0));
  +        assertSame(TWO, view.get(1));
  +    }        
  +    
  +    public void testListAddIndexed() {
  +        OrderedSet set = (OrderedSet) makeEmptySet();
  +        List view = set.asList();
  +        set.add(ZERO);
  +        set.add(TWO);
  +        
  +        set.add(1, ONE);
  +        assertEquals(3, set.size());
  +        assertSame(ZERO, set.get(0));
  +        assertSame(ONE, set.get(1));
  +        assertSame(TWO, set.get(2));
  +        
  +        set.add(0, ONE);
  +        assertEquals(3, set.size());
  +        assertSame(ZERO, set.get(0));
  +        assertSame(ONE, set.get(1));
  +        assertSame(TWO, set.get(2));
  +        
  +        List list = new ArrayList();
  +        list.add(ZERO);
  +        list.add(TWO);
  +        
  +        set.addAll(0, list);
  +        assertEquals(3, set.size());
  +        assertSame(ZERO, set.get(0));
  +        assertSame(ONE, set.get(1));
  +        assertSame(TWO, set.get(2));
  +        
  +        list.add(0, THREE); // list = [3,0,2]
  +        set.remove(TWO);    //  set = [0,1]
  +        set.addAll(1, list);
  +        assertEquals(4, set.size());
  +        assertSame(ZERO, set.get(0));
  +        assertSame(THREE, set.get(1));
  +        assertSame(TWO, set.get(2));
  +        assertSame(ONE, set.get(3));
       }
       
   }