From c3c28e3daeb3ee747370ff6c7a859744f8e85859 Mon Sep 17 00:00:00 2001 From: Stephen Colebourne Date: Sat, 20 Sep 2003 16:57:47 +0000 Subject: [PATCH] Enhance OrderedSet to support List like functions git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/collections/trunk@131172 13f79535-47bb-0310-9956-ffa450edef68 --- .../collections/decorators/OrderedSet.java | 104 ++++++++++++++++-- .../decorators/TestOrderedSet.java | 78 ++++++++++++- 2 files changed, 173 insertions(+), 9 deletions(-) diff --git a/src/java/org/apache/commons/collections/decorators/OrderedSet.java b/src/java/org/apache/commons/collections/decorators/OrderedSet.java index 4cbd4fafb..444186ae3 100644 --- a/src/java/org/apache/commons/collections/decorators/OrderedSet.java +++ b/src/java/org/apache/commons/collections/decorators/OrderedSet.java @@ -1,5 +1,5 @@ /* - * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/decorators/Attic/OrderedSet.java,v 1.1 2003/09/09 22:28:35 scolebourne Exp $ + * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/decorators/Attic/OrderedSet.java,v 1.2 2003/09/20 16:57:47 scolebourne Exp $ * ==================================================================== * * The Apache Software License, Version 1.1 @@ -59,6 +59,8 @@ package org.apache.commons.collections.decorators; 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,13 +69,20 @@ import java.util.Set; * Decorates a Set to ensure that the order of addition * is retained and used by the iterator. *

- * 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. *

- * The order can be observed via the iterator or toArray methods. + * The OrderedSet also has various useful direct methods. These include many + * from List, such as get(int), remove(int) + * and indexOf(int). An unmodifiable List view of + * the set can be obtained via asList(). + *

+ * This class cannot implement the List interface directly as + * various interface methods (notably equals/hashCode) are incompatable with a set. * * @since Commons Collections 3.0 - * @version $Revision: 1.1 $ $Date: 2003/09/09 22:28:35 $ + * @version $Revision: 1.2 $ $Date: 2003/09/20 16:57:47 $ * * @author Stephen Colebourne * @author Henning P. Schmiedehausen @@ -81,18 +90,35 @@ import java.util.Set; 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. + *

+ * An ArrayList 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. + *

+ * A HashSet 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). * @@ -101,7 +127,34 @@ public class OrderedSet extends AbstractSetDecorator implements Set { */ 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. + *

+ * 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 @@ public class OrderedSet extends AbstractSetDecorator implements Set { 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. */ diff --git a/src/test/org/apache/commons/collections/decorators/TestOrderedSet.java b/src/test/org/apache/commons/collections/decorators/TestOrderedSet.java index e26cf5290..fe75e6e15 100644 --- a/src/test/org/apache/commons/collections/decorators/TestOrderedSet.java +++ b/src/test/org/apache/commons/collections/decorators/TestOrderedSet.java @@ -1,5 +1,5 @@ /* - * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/decorators/Attic/TestOrderedSet.java,v 1.1 2003/09/09 22:28:36 scolebourne Exp $ + * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/decorators/Attic/TestOrderedSet.java,v 1.2 2003/09/20 16:57:47 scolebourne Exp $ * ==================================================================== * * The Apache Software License, Version 1.1 @@ -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; @@ -71,7 +73,7 @@ import org.apache.commons.collections.TestSet; * implementation. * * @since Commons Collections 3.0 - * @version $Revision: 1.1 $ $Date: 2003/09/09 22:28:36 $ + * @version $Revision: 1.2 $ $Date: 2003/09/20 16:57:47 $ * * @author Henning P. Schmiedehausen * @author Stephen Colebourne @@ -136,4 +138,76 @@ public class TestOrderedSet extends TestSet { } } + 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)); + } + }