Sounds like a sensible addition to [collections]. At some point, one of the
commiters will take a look (I've been on holiday for the last few days...).
Stephen

----- Original Message -----
From: "Henning P. Schmiedehausen" <[EMAIL PROTECTED]>
Newsgroups: hometree.jakarta.commons.dev
To: <[EMAIL PROTECTED]>
Sent: Wednesday, March 26, 2003 10:10 AM
Subject: [COLLECTIONS] OrderedSet - Bugzilla # 18006


> Hi,
>
> some days ago I put a new class for the Collections component into
> bugzilla bug haven't received any feedback on this. So I resend here. :-)
>
> --- cut ---
> This is a class implementing the Set interface but keeping the
> sequence of the objects added to the set.
>
> The patch contains unit tests based on TestSet and it passed all the
> unit tests by the commons collections suite. It is fully documented
> and I could use it in the Turbine project. Please add!
> --- cut ---
>
> You can also get the following attachment from bugzilla:
>
> http://issues.apache.org/bugzilla/showattachment.cgi?attach_id=5343
>
> Regards
> Henning
>
>
> diff --exclude=CVS -Nurb
collections/src/java/org/apache/commons/collections/OrderedSet.java
collections.p/src/java/org/apache/commons/collections/OrderedSet.java
> --- collections/src/java/org/apache/commons/collections/OrderedSet.java
Thu Jan  1 01:00:00 1970
> +++ collections.p/src/java/org/apache/commons/collections/OrderedSet.java
Fri Mar 14 18:57:24 2003
> @@ -0,0 +1,509 @@
> +/*
> + * $Header$
> + * $Revision$
> + * $Date$
> + *
> + * ====================================================================
> + *
> + * The Apache Software License, Version 1.1
> + *
> + * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
> + * reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + *
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in
> + *    the documentation and/or other materials provided with the
> + *    distribution.
> + *
> + * 3. The end-user documentation included with the redistribution, if
> + *    any, must include the following acknowlegement:
> + *       "This product includes software developed by the
> + *        Apache Software Foundation (http://www.apache.org/)."
> + *    Alternately, this acknowlegement may appear in the software itself,
> + *    if and wherever such third-party acknowlegements normally appear.
> + *
> + * 4. The names "The Jakarta Project", "Commons", and "Apache Software
> + *    Foundation" must not be used to endorse or promote products derived
> + *    from this software without prior written permission. For written
> + *    permission, please contact [EMAIL PROTECTED]
> + *
> + * 5. Products derived from this software may not be called "Apache"
> + *    nor may "Apache" appear in their names without prior written
> + *    permission of the Apache Group.
> + *
> + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
> + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> + * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
> + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
> + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
> + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
> + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + * ====================================================================
> + *
> + * This software consists of voluntary contributions made by many
> + * individuals on behalf of the Apache Software Foundation.  For more
> + * information on the Apache Software Foundation, please see
> + * <http://www.apache.org/>.
> + *
> + */
> +
> +package org.apache.commons.collections;
> +
> +import java.util.ArrayList;
> +import java.util.Collection;
> +import java.util.ConcurrentModificationException;
> +import java.util.Iterator;
> +import java.util.List;
> +import java.util.Set;
> +
> +/**
> + * A [EMAIL PROTECTED] Collection} that contains each object only once but keeps the
sequence
> + * of the objects like a list.
> + *
> + * @author <a hef="mailto:[EMAIL PROTECTED]">Henning P. Schmiedehausen</a>
> + * @version $Id$
> + */
> +
> +public class OrderedSet
> +        implements Set
> +{
> +    /** Internal list to hold the sequence of objects */
> +    private List setList = null;
> +
> +    /**
> +     * Constructs a new, empty Set.
> +     */
> +    public OrderedSet()
> +    {
> +        clear();
> +    }
> +
> +    /**
> +     * Constructs a new Set from a given Collection. If
> +     * the collection contains an object twice, only one
> +     * is added.
> +     *
> +     * @param c A collection Object
> +     */
> +    public OrderedSet(Collection c)
> +    {
> +        clear();
> +
> +        if ( c != null)
> +        {
> +            for (Iterator it = c.iterator(); it.hasNext();)
> +            {
> +                Object elem = it.next();
> +                add(elem);
> +            }
> +        }
> +    }
> +
> +    /**
> +     * Purge everything from the set.
> +     *
> +     * @throws UnsupportedOperationException if the clear method
> +     *   is not supported by this set.
> +     */
> +    public void clear()
> +    {
> +        this.setList = new ArrayList();
> +    }
> +
> +    /**
> +     * Returns the number of objects in this set.
> +     *
> +     * @return The size of the set.
> +     */
> +    public int size()
> +    {
> +        return setList.size();
> +    }
> +
> +    /**
> +     * Returns true if this set is empty.
> +     *
> +     * @return true if this set is empty.
> +     */
> +    public boolean isEmpty()
> +    {
> +        return setList.isEmpty();
> +    }
> +
> +    /**
> +     * Returns an iterator over the objects in this set.
> +     * This set guarantees that they are in the same sequence
> +     * as they were added. If an object is added multiple
> +     * times, then its place is the first addition to the set.
> +     *
> +     * @return An iterator for this set.
> +     */
> +    public Iterator iterator()
> +    {
> +        return new OrderedSetIterator(setList);
> +    }
> +
> +    /**
> +     * Adds an object to the set.
> +     * This set keeps the sequence of the additions.
> +     *
> +     * @param o The object to be added to this set.
> +     *
> +     * @return true if this set did not already contain the specified
> +     *         object.
> +     *
> +     * @throws UnsupportedOperationException if the add method is not
> +     *        supported by this set.
> +     * @throws ClassCastException if the class of the specified object
> +     *        prevents it from being added to this set.
> +     * @throws IllegalArgumentException if some aspect of this object
> +     *         prevents it from being added to this set.
> +     */
> +    public boolean add(Object o)
> +    {
> +        synchronized (setList)
> +        {
> +            if (setList.contains(o))
> +            {
> +                return false;
> +            }
> +            setList.add(o);
> +            return true;
> +        }
> +    }
> +
> +    /**
> +     * Adds all objects in the specified collection to this set.
> +     *
> +     * @param c A collection object, whose objects should be added
> +     *
> +     * @return true if any object in the collection was actually added.
> +     *
> +     * @throws UnsupportedOperationException if the addAll method is
> +     *   not supported by this set.
> +     * @throws ClassCastException if the class of some object of the
> +     *   specified collection prevents it from being added to this
> +     *   set.
> +     * @throws IllegalArgumentException if some aspect of some object of
the
> +     *   specified collection prevents it from being added to this
> +     *   set.
> +     */
> +    public boolean addAll(Collection c)
> +    {
> +        synchronized (setList)
> +        {
> +            boolean result = false;
> +
> +            if (c != null)
> +            {
> +                for (Iterator it = c.iterator(); it.hasNext(); )
> +                {
> +                    Object o = it.next();
> +                    if (!setList.contains(o))
> +                    {
> +                        result |= setList.add(o);
> +                    }
> +                }
> +            }
> +            return result;
> +        }
> +    }
> +
> +    /**
> +     * Removes an object from the set.
> +     *
> +     * @param o object to be removed from this set, if present.
> +     *
> +     * @return true if the set contained the specified object.
> +     *
> +     * @throws UnsupportedOperationException if the remove method is
> +     *         not supported by this set.
> +     */
> +    public boolean remove(Object o)
> +    {
> +        return setList.remove(o);
> +    }
> +
> +    /**
> +     * Remove all the objects given in the supplied collection.
> +     *
> +     * @param c A collection with the objects to keep.
> +     *
> +     * @return true if any object was removed.
> +     *
> +     * @throws UnsupportedOperationException if the removeAll
> +     *   method is not supported by this Collection.
> +     */
> +    public boolean removeAll(Collection c)
> +    {
> +        synchronized (setList)
> +        {
> +            boolean result = false;
> +
> +            if (c != null)
> +            {
> +                for (Iterator it = setList.iterator(); it.hasNext(); )
> +                {
> +                    Object o = it.next();
> +                    if (c.contains(o))
> +                    {
> +                        it.remove();
> +                        result = true;
> +                    }
> +                }
> +            }
> +            return result;
> +        }
> +    }
> +
> +    /**
> +     * Returns true if this set contains an object.
> +     *
> +     * @param o The wanted object
> +     *
> +     * @return true if this set contains this object
> +     */
> +    public boolean contains(Object o)
> +    {
> +        return setList.contains(o);
> +    }
> +
> +    /**
> +     * Returns true if this set contains all of the objects in the
> +     * given collection object.
> +     *
> +     * @param c A collection to be checked.
> +     *
> +     * @return true if this set contains all of the objects in this
collection.
> +     */
> +    public boolean containsAll(Collection c)
> +    {
> +        return setList.containsAll(c);
> +    }
> +
> +    /**
> +     * Keep only the objects given in the supplied collection. Remove
> +     * all other objects.
> +     *
> +     * @param c A collection with the objects to keep.
> +     *
> +     * @return true if any object was removed.
> +     *
> +     * @throws UnsupportedOperationException if the retainAll method
> +     *   is not supported by this Collection.
> +     */
> +    public boolean retainAll(Collection c)
> +    {
> +        synchronized (setList)
> +        {
> +            boolean result = false;
> +
> +            if (c != null)
> +            {
> +                for (Iterator it = setList.iterator(); it.hasNext(); )
> +                {
> +                    Object o = it.next();
> +                    if (!c.contains(o))
> +                    {
> +                        it.remove();
> +                        result = true;
> +                    }
> +                }
> +            }
> +            return result;
> +        }
> +    }
> +
> +    /**
> +     * Returns an array containing all of the objects in this set.
> +     *
> +     * @return An array with all objects in this set.
> +     */
> +    public Object[] toArray()
> +    {
> +        return setList.toArray();
> +    }
> +
> +    /**
> +     * Returns an array containing all of the objects in this set
> +     * with the specified runtime type.
> +     *
> +     * @param a An array to put all the objects in. If it is
> +     * not big enough, a new array is allocated which
> +     *          has the needed size.
> +     *
> +     * @return An array containing the objects of this set.
> +     *
> +     * @throws    ArrayStoreException Objects couldn't be fit into
> +     *            the required Array type.
> +     */
> +    public Object[] toArray(Object a[])
> +    {
> +        return setList.toArray(a);
> +    }
> +
> +    /**
> +     * Checks whether the supplied object is equal to this set.
> +     *
> +     * @param o Object to be checked.
> +     *
> +     * @return true if both objects are equal.
> +     */
> +    public boolean equals(Object o)
> +    {
> +        synchronized (setList)
> +        {
> +            if (o == null  || (! (o instanceof Set)))
> +            {
> +                return false;
> +            }
> +
> +            Set s = (Set) o;
> +
> +            if (s.size () != setList.size())
> +            {
> +                return false;
> +            }
> +
> +            // Our iterator is fast, our lookups are slow...
> +            for (Iterator it = setList.iterator(); it.hasNext(); )
> +            {
> +                if (!s.contains(it.next()))
> +                {
> +                    return false;
> +                }
> +            }
> +
> +            return true;
> +        }
> +    }
> +
> +    /**
> +     * Returns the hash code for this set.
> +     *
> +     * @return the hash code for this set.
> +     */
> +    public int hashCode()
> +    {
> +        synchronized (setList)
> +        {
> +            int h = 0;
> +
> +            for (Iterator it = setList.iterator(); it.hasNext(); )
> +            {
> +                Object o = it.next();
> +
> +                if (o != null)
> +                {
> +                    h += o.hashCode();
> +                }
> +            }
> +
> +            return h;
> +        }
> +    }
> +
> +    /**
> +     * And a pretty print toString()
> +     *
> +     * @return A pretty formatted Set of elements.
> +     */
> +    public String toString()
> +    {
> +        synchronized(setList)
> +        {
> +            StringBuffer sb = new StringBuffer();
> +
> +            sb.append('[');
> +
> +            for (Iterator it = setList.iterator(); it.hasNext(); )
> +            {
> +                sb.append(String.valueOf(it.next()));
> +
> +                if (it.hasNext())
> +                {
> +                    sb.append(", ");
> +                }
> +            }
> +            sb.append(']');
> +            return sb.toString();
> +        }
> +    }
> +
> +    /**
> +     * Internal iterator to pass the CoModification test
> +     *
> +     */
> +    private class OrderedSetIterator
> +            implements Iterator
> +    {
> +        /** Object we iterate on */
> +        Collection c;
> +
> +        /** Internal iterator reference */
> +        Iterator it;
> +
> +        /**
> +         * C'tor
> +         */
> +        private OrderedSetIterator(Collection c)
> +        {
> +            this.c = c;
> +            this.it = c.iterator();
> +        }
> +
> +        /**
> +         * Next Element
> +         */
> +        public Object next()
> +        {
> +            coModCheck();
> +            return it.next();
> +        }
> +
> +        /**
> +         * has another element
> +         *
> +         * @return True if yes
> +         */
> +        public boolean hasNext()
> +        {
> +            coModCheck();
> +            return it.hasNext();
> +        }
> +
> +        /**
> +         * Remove current element
> +         *
> +         */
> +        public void remove()
> +        {
> +            coModCheck();
> +            it.remove();
> +        }
> +
> +        /**
> +         * Clear would have pulled the list
> +         * from under us.
> +         */
> +        private void coModCheck()
> +        {
> +            if (setList != c)
> +            {
> +                throw new ConcurrentModificationException();
> +            }
> +        }
> +    }
> +}
> diff --exclude=CVS -Nurb
collections/src/java/org/apache/commons/collections/package.html
collections.p/src/java/org/apache/commons/collections/package.html
> --- collections/src/java/org/apache/commons/collections/package.html Sun
Dec  8 16:30:58 2002
> +++ collections.p/src/java/org/apache/commons/collections/package.html Fri
Mar 14 19:02:03 2003
> @@ -75,6 +75,12 @@
>          </td>
>        </tr>
>        <tr>
> +        <td valign="top">Set Implementations</td>
> +        <td>
> +          [EMAIL PROTECTED] org.apache.commons.collections.OrderedSet}<br>
> +        </td>
> +      </tr>
> +      <tr>
>          <td valign="top">Utilities</td>
>          <td valign="top">
>            [EMAIL PROTECTED] org.apache.commons.collections.BagUtils}<br>
> diff --exclude=CVS -Nurb
collections/src/test/org/apache/commons/collections/TestAll.java
collections.p/src/test/org/apache/commons/collections/TestAll.java
> --- collections/src/test/org/apache/commons/collections/TestAll.java Sun
Mar  9 01:07:41 2003
> +++ collections.p/src/test/org/apache/commons/collections/TestAll.java Fri
Mar 14 17:56:36 2003
> @@ -108,6 +108,7 @@
>          suite.addTest(TestUnboundedFifoBuffer.suite());
>          suite.addTest(TestReferenceMap.suite());
>          suite.addTest(TestIteratorUtils.suite());
> +        suite.addTest(TestOrderedSet.suite());
>
suite.addTest(org.apache.commons.collections.comparators.TestAll.suite());
>
suite.addTest(org.apache.commons.collections.iterators.TestAll.suite());
>
suite.addTest(org.apache.commons.collections.primitives.TestAll.suite());
> diff --exclude=CVS -Nurb
collections/src/test/org/apache/commons/collections/TestOrderedSet.java
collections.p/src/test/org/apache/commons/collections/TestOrderedSet.java
> ---
collections/src/test/org/apache/commons/collections/TestOrderedSet.java Thu
Jan  1 01:00:00 1970
> +++
collections.p/src/test/org/apache/commons/collections/TestOrderedSet.java
Fri Mar 14 18:58:03 2003
> @@ -0,0 +1,155 @@
> +/*
> + * $Header$
> + * $Revision$
> + * $Date$
> + *
> + * ====================================================================
> + *
> + * The Apache Software License, Version 1.1
> + *
> + * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
> + * reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + *
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in
> + *    the documentation and/or other materials provided with the
> + *    distribution.
> + *
> + * 3. The end-user documentation included with the redistribution, if
> + *    any, must include the following acknowlegement:
> + *       "This product includes software developed by the
> + *        Apache Software Foundation (http://www.apache.org/)."
> + *    Alternately, this acknowlegement may appear in the software itself,
> + *    if and wherever such third-party acknowlegements normally appear.
> + *
> + * 4. The names "The Jakarta Project", "Commons", and "Apache Software
> + *    Foundation" must not be used to endorse or promote products derived
> + *    from this software without prior written permission. For written
> + *    permission, please contact [EMAIL PROTECTED]
> + *
> + * 5. Products derived from this software may not be called "Apache"
> + *    nor may "Apache" appear in their names without prior written
> + *    permission of the Apache Group.
> + *
> + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
> + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> + * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
> + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
> + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
> + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
> + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + * ====================================================================
> + *
> + * This software consists of voluntary contributions made by many
> + * individuals on behalf of the Apache Software Foundation.  For more
> + * information on the Apache Software Foundation, please see
> + * <http://www.apache.org/>.
> + *
> + */
> +
> +package org.apache.commons.collections;
> +
> +import java.util.Iterator;
> +import java.util.Set;
> +
> +import junit.framework.Test;
> +import junit.framework.TestSuite;
> +
> +/**
> + * Extension of [EMAIL PROTECTED] TestSet} for exercising the [EMAIL PROTECTED] 
> OrderedSet}
> + * implementation.
> + *
> + * @author <a hef="mailto:[EMAIL PROTECTED]">Henning P. Schmiedehausen</a>
> + * @version $Id$
> + */
> +public class TestOrderedSet
> +        extends TestSet
> +{
> +    public TestOrderedSet(String testName)
> +    {
> +        super(testName);
> +    }
> +
> +    public static Test suite()
> +    {
> +        return new TestSuite(TestOrderedSet.class);
> +    }
> +
> +    public static void main(String args[])
> +    {
> +        String[] testCaseName = { TestOrderedSet.class.getName() };
> +        junit.textui.TestRunner.main(testCaseName);
> +    }
> +
> +    public Set makeEmptySet()
> +    {
> +        return new OrderedSet();
> +    }
> +
> +    public Set setupSet()
> +    {
> +        Set set = makeEmptySet();
> +
> +        for (int i = 0; i < 10 ; i++)
> +        {
> +            set.add(Integer.toString(i));
> +        }
> +        return set;
> +    }
> +
> +    public void testOrdering()
> +    {
> +        Set set = setupSet();
> +        Iterator it = set.iterator();
> +
> +        for (int i = 0; i < 10 ; i++)
> +        {
> +            assertEquals("Sequence is wrong" ,
> +                    Integer.toString(i), it.next());
> +        }
> +
> +        for (int i = 0; i < 10 ; i += 2)
> +        {
> +            assertTrue("Must be able to remove int",
> +                    set.remove(Integer.toString(i)));
> +        }
> +
> +        it = set.iterator();
> +        for (int i = 1; i < 10 ; i += 2)
> +        {
> +            assertEquals("Sequence is wrong after remove ",
> +                    Integer.toString(i), it.next());
> +        }
> +
> +        for (int i = 0; i < 10 ; i++)
> +        {
> +            set.add(Integer.toString(i));
> +        }
> +
> +        assertEquals("Size of set is wrong!", 10, set.size());
> +
> +        it = set.iterator();
> +        for (int i = 1; i < 10 ; i += 2)
> +        {
> +            assertEquals("Sequence is wrong",
> +                    Integer.toString(i), it.next());
> +        }
> +        for (int i = 0; i < 10 ; i += 2)
> +        {
> +            assertEquals("Sequence is wrong",
> +                    Integer.toString(i), it.next());
> +        }
> +    }
> +}
> --
> Dipl.-Inf. (Univ.) Henning P. Schmiedehausen          INTERMETA GmbH
> [EMAIL PROTECTED]        +49 9131 50 654 0   http://www.intermeta.de/
>
> Java, perl, Solaris, Linux, xSP Consulting, Web Services
> freelance consultant -- Jakarta Turbine Development  -- hero for hire
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to