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 2006/05/06 18:10:32 UTC

svn commit: r400329 - in /jakarta/commons/proper/collections/trunk: ./ src/java/org/apache/commons/collections/iterators/ src/test/org/apache/commons/collections/iterators/

Author: scolebourne
Date: Sat May  6 09:10:31 2006
New Revision: 400329

URL: http://svn.apache.org/viewcvs?rev=400329&view=rev
Log:
Add ReverseListIterator
rfe 39224, including code from Serge Knystautas

Added:
    jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/iterators/ReverseListIterator.java   (with props)
    jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestReverseListIterator.java   (with props)
Modified:
    jakarta/commons/proper/collections/trunk/RELEASE-NOTES.html
    jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestAll.java

Modified: jakarta/commons/proper/collections/trunk/RELEASE-NOTES.html
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/RELEASE-NOTES.html?rev=400329&r1=400328&r2=400329&view=diff
==============================================================================
--- jakarta/commons/proper/collections/trunk/RELEASE-NOTES.html (original)
+++ jakarta/commons/proper/collections/trunk/RELEASE-NOTES.html Sat May  6 09:10:31 2006
@@ -58,6 +58,7 @@
 <li>DefaultedMap - Returns a default value when the key is not found, without adding the default value to the map itself [30911]</li>
 <li>GrowthList - Decorator that causes set and indexed add to expand the list rather than throw IndexOutOfBoundsException [34171]</li>
 <li>LoopingListIterator - When the end of the list is reached the iteration continues from the start [30166]</li>
+<li>ReverseListIterator - A list iterator that returns the elements from the list in reverse order [39224]</li>
 <li>BoundedBuffer - A new wrapper class which can make any buffer bounded [37473]</li>
 </ul>
 

Added: jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/iterators/ReverseListIterator.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/iterators/ReverseListIterator.java?rev=400329&view=auto
==============================================================================
--- jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/iterators/ReverseListIterator.java (added)
+++ jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/iterators/ReverseListIterator.java Sat May  6 09:10:31 2006
@@ -0,0 +1,174 @@
+/*
+ *  Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.commons.collections.iterators;
+
+import java.util.List;
+import java.util.ListIterator;
+
+import org.apache.commons.collections.ResettableListIterator;
+
+/**
+ * Iterates backwards through a List, starting with the last element
+ * and continuing to the first. This is useful for looping around
+ * a list in reverse order without needing to actually reverse the list.
+ * <p>
+ * The first call to <code>next()</code> will return the last element
+ * from the list, and so on. The <code>hasNext()</code> method works
+ * in concert with the <code>next()</code> method as expected.
+ * However, the <code>nextIndex()</code> method returns the correct
+ * index in the list, thus it starts high and reduces as the iteration
+ * continues. The previous methods work similarly.
+ *
+ * @author Serge Knystautas
+ * @author Stephen Colebourne
+ * @version $Revision: $ $Date$
+ */
+public class ReverseListIterator implements ResettableListIterator {
+
+    /** The list being wrapped. */
+    private final List list;
+    /** The list iterator being wrapped. */
+    private ListIterator iterator;
+    /** Flag to indicate if updating is possible at the moment. */
+    private boolean validForUpdate = true;
+
+    /**
+     * Constructor that wraps a list.
+     *
+     * @param list  the list to create a reversed iterator for
+     * @throws NullPointerException if the list is null
+     */
+    public ReverseListIterator(List list) {
+        super();
+        this.list = list;
+        iterator = list.listIterator(list.size());
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Checks whether there is another element.
+     *
+     * @return true if there is another element
+     */
+    public boolean hasNext() {
+        return iterator.hasPrevious();
+    }
+
+    /**
+     * Gets the next element.
+     * The next element is the previous in the list.
+     *
+     * @return the next element in the iterator
+     */
+    public Object next() {
+        Object obj = iterator.previous();
+        validForUpdate = true;
+        return obj;
+    }
+
+    /**
+     * Gets the index of the next element.
+     *
+     * @return the index of the next element in the iterator
+     */
+    public int nextIndex() {
+        return iterator.previousIndex();
+    }
+
+    /**
+     * Checks whether there is a previous element.
+     *
+     * @return true if there is a previous element
+     */
+    public boolean hasPrevious() {
+        return iterator.hasNext();
+    }
+
+    /**
+     * Gets the previous element.
+     * The next element is the previous in the list.
+     *
+     * @return the previous element in the iterator
+     */
+    public Object previous() {
+        Object obj = iterator.next();
+        validForUpdate = true;
+        return obj;
+    }
+
+    /**
+     * Gets the index of the previous element.
+     *
+     * @return the index of the previous element in the iterator
+     */
+    public int previousIndex() {
+        return iterator.nextIndex();
+    }
+
+    /**
+     * Removes the last returned element.
+     *
+     * @throws UnsupportedOperationException if the list is unmodifiable
+     * @throws IllegalStateException if there is no element to remove
+     */
+    public void remove() {
+        if (validForUpdate == false) {
+            throw new IllegalStateException("Cannot remove from list until next() or previous() called");
+        }
+        iterator.remove();
+    }
+
+    /**
+     * Replaces the last returned element.
+     *
+     * @param obj  the object to set
+     * @throws UnsupportedOperationException if the list is unmodifiable
+     * @throws IllegalStateException if the iterator is not in a valid state for set
+     */
+    public void set(Object obj) {
+        if (validForUpdate == false) {
+            throw new IllegalStateException("Cannot set to list until next() or previous() called");
+        }
+        iterator.set(obj);
+    }
+
+    /**
+     * Adds a new element to the list between the next and previous elements.
+     *
+     * @param obj  the object to add
+     * @throws UnsupportedOperationException if the list is unmodifiable
+     * @throws IllegalStateException if the iterator is not in a valid state for set
+     */
+    public void add(Object obj) {
+        // the validForUpdate flag is needed as the necessary previous()
+        // method call re-enables remove and add
+        if (validForUpdate == false) {
+            throw new IllegalStateException("Cannot add to list until next() or previous() called");
+        }
+        validForUpdate = false;
+        iterator.add(obj);
+        iterator.previous();
+    }
+
+    /**
+     * Resets the iterator back to the start (which is the
+     * end of the list as this is a reversed iterator)
+     */
+    public void reset() {
+        iterator = list.listIterator(list.size());
+    }
+
+}

Propchange: jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/iterators/ReverseListIterator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/iterators/ReverseListIterator.java
------------------------------------------------------------------------------
    svn:keywords = "author date id revision"

Modified: jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestAll.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestAll.java?rev=400329&r1=400328&r2=400329&view=diff
==============================================================================
--- jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestAll.java (original)
+++ jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestAll.java Sat May  6 09:10:31 2006
@@ -48,6 +48,7 @@
         suite.addTest(TestListIteratorWrapper.suite());
         suite.addTest(TestLoopingIterator.suite());
         suite.addTest(TestLoopingListIterator.suite());
+        suite.addTest(TestReverseListIterator.suite());
         suite.addTest(TestSingletonIterator.suite());
         suite.addTest(TestSingletonIterator2.suite());
         suite.addTest(TestSingletonListIterator.suite());

Added: jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestReverseListIterator.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestReverseListIterator.java?rev=400329&view=auto
==============================================================================
--- jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestReverseListIterator.java (added)
+++ jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestReverseListIterator.java Sat May  6 09:10:31 2006
@@ -0,0 +1,170 @@
+/*
+ *  Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.commons.collections.iterators;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+import org.apache.commons.collections.ResettableListIterator;
+
+/**
+ * Tests the ReverseListIterator.
+ *
+ * @version $Revision: $ $Date$
+ */
+public class TestReverseListIterator extends AbstractTestListIterator {
+
+    protected String[] testArray = { "One", "Two", "Three", "Four" };
+
+    public static void main(String args[]) {
+        String[] testCaseName = { TestReverseListIterator.class.getName() };
+        TestRunner.main(testCaseName);
+    }
+
+    public static Test suite() {
+        return new TestSuite(TestReverseListIterator.class);
+    }
+
+    public TestReverseListIterator(String testName) {
+        super(testName);
+    }
+
+    public ListIterator makeEmptyListIterator() {
+        List list = new ArrayList();
+        return new ReverseListIterator(list);
+    }
+
+    public ListIterator makeFullListIterator() {
+        List list = new ArrayList(Arrays.asList(testArray));
+        return new ReverseListIterator(list);
+    }
+
+    // overrides
+    //-----------------------------------------------------------------------
+    public void testEmptyListIteratorIsIndeedEmpty() {
+        ListIterator it = makeEmptyListIterator();
+        
+        assertEquals(false, it.hasNext());
+        assertEquals(-1, it.nextIndex());  // reversed index
+        assertEquals(false, it.hasPrevious());
+        assertEquals(0, it.previousIndex());  // reversed index
+        
+        // next() should throw a NoSuchElementException
+        try {
+            it.next();
+            fail("NoSuchElementException must be thrown from empty ListIterator");
+        } catch (NoSuchElementException e) {
+        }
+        
+        // previous() should throw a NoSuchElementException
+        try {
+            it.previous();
+            fail("NoSuchElementException must be thrown from empty ListIterator");
+        } catch (NoSuchElementException e) {
+        }
+    }
+
+    public void testWalkForwardAndBack() {
+        ArrayList list = new ArrayList();
+        ListIterator it = makeFullListIterator();
+        while (it.hasNext()) {
+            list.add(it.next());
+        }
+        
+        // check state at end
+        assertEquals(false, it.hasNext());
+        assertEquals(true, it.hasPrevious());
+        
+        // this had to be commented out, as there is a bug in the JDK before JDK1.5
+        // where calling previous at the start of an iterator would push the cursor
+        // back to an invalid negative value
+//        try {
+//            it.next();
+//            fail("NoSuchElementException must be thrown from next at end of ListIterator");
+//        } catch (NoSuchElementException e) {
+//        }
+        
+        // loop back through comparing
+        for (int i = list.size() - 1; i >= 0; i--) {
+            assertEquals("" + i, list.size() - i - 2, it.nextIndex());  // reversed index
+            assertEquals(list.size() - i - 1, it.previousIndex());  // reversed index
+            
+            Object obj = list.get(i);
+            assertEquals(obj, it.previous());
+        }
+        
+        // check state at start
+        assertEquals(true, it.hasNext());
+        assertEquals(false, it.hasPrevious());
+        try {
+            it.previous();
+            fail("NoSuchElementException must be thrown from previous at start of ListIterator");
+        } catch (NoSuchElementException e) {
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    public void testReverse() {
+        ListIterator it = makeFullListIterator();
+        assertEquals(true, it.hasNext());
+        assertEquals(3, it.nextIndex());
+        assertEquals(false, it.hasPrevious());
+        assertEquals(4, it.previousIndex());
+        assertEquals("Four", it.next());
+        assertEquals(2, it.nextIndex());
+        assertEquals(true, it.hasNext());
+        assertEquals(3, it.previousIndex());
+        assertEquals(true, it.hasPrevious());
+        assertEquals("Three", it.next());
+        assertEquals(true, it.hasNext());
+        assertEquals(1, it.nextIndex());
+        assertEquals(true, it.hasPrevious());
+        assertEquals(2, it.previousIndex());
+        assertEquals("Two", it.next());
+        assertEquals(true, it.hasNext());
+        assertEquals(0, it.nextIndex());
+        assertEquals(true, it.hasPrevious());
+        assertEquals(1, it.previousIndex());
+        assertEquals("One", it.next());
+        assertEquals(false, it.hasNext());
+        assertEquals(-1, it.nextIndex());
+        assertEquals(true, it.hasPrevious());
+        assertEquals(0, it.previousIndex());
+        assertEquals("One", it.previous());
+        assertEquals("Two", it.previous());
+        assertEquals("Three", it.previous());
+        assertEquals("Four", it.previous());
+    }
+
+    public void testReset() {
+        ResettableListIterator it = (ResettableListIterator) makeFullListIterator();
+        assertEquals("Four", it.next());
+        it.reset();
+        assertEquals("Four", it.next());
+        it.next();
+        it.next();
+        it.reset();
+        assertEquals("Four", it.next());
+    }
+
+}

Propchange: jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestReverseListIterator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestReverseListIterator.java
------------------------------------------------------------------------------
    svn:keywords = "author date id revision"



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org