You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by tn...@apache.org on 2015/05/28 11:58:10 UTC

svn commit: r1682196 - in /commons/proper/collections/trunk/src: changes/ main/java/org/apache/commons/collections4/ main/java/org/apache/commons/collections4/iterators/ test/java/org/apache/commons/collections4/iterators/

Author: tn
Date: Thu May 28 09:58:09 2015
New Revision: 1682196

URL: http://svn.apache.org/r1682196
Log:
Add unit test for ZippingIterator, add factory methods to IteratorUtils, add changelog entry.

Added:
    commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/iterators/ZippingIteratorTest.java   (with props)
Modified:
    commons/proper/collections/trunk/src/changes/changes.xml
    commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/IteratorUtils.java
    commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/iterators/ZippingIterator.java

Modified: commons/proper/collections/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/changes/changes.xml?rev=1682196&r1=1682195&r2=1682196&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/changes/changes.xml (original)
+++ commons/proper/collections/trunk/src/changes/changes.xml Thu May 28 09:58:09 2015
@@ -28,6 +28,9 @@
       added to "IterableUtils" and "IteratorUtils".
     </action>
     <action issue="COLLECTIONS-464" dev="tn" type="add">
+      Added new "ZippingIterator" and factory methods "IteratorUtils#zippingIterator(...)".
+    </action>
+    <action issue="COLLECTIONS-464" dev="tn" type="add">
       Added new decorator "SkippingIterator" and factory methods "IteratorUtils#skippingIterator(...)".
     </action>
     <action issue="COLLECTIONS-556" dev="tn" type="add">

Modified: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/IteratorUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/IteratorUtils.java?rev=1682196&r1=1682195&r2=1682196&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/IteratorUtils.java (original)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/IteratorUtils.java Thu May 28 09:58:09 2015
@@ -61,6 +61,7 @@ import org.apache.commons.collections4.i
 import org.apache.commons.collections4.iterators.UnmodifiableIterator;
 import org.apache.commons.collections4.iterators.UnmodifiableListIterator;
 import org.apache.commons.collections4.iterators.UnmodifiableMapIterator;
+import org.apache.commons.collections4.iterators.ZippingIterator;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
@@ -489,22 +490,6 @@ public class IteratorUtils {
         return new BoundedIterator<E>(iterator, offset, max);
     }
 
-    // Skipping
-    //-----------------------------------------------------------------------
-    /**
-     * Decorates the specified iterator to skip the first N elements.
-     *
-     * @param <E>  the element type
-     * @param iterator  the iterator to decorate
-     * @param offset  the first number of elements to skip
-     * @return a new skipping iterator
-     * @throws IllegalArgumentException if the iterator is null or offset is negative
-     * @since 4.1
-     */
-    public static <E> SkippingIterator<E> skippingIterator(final Iterator<E> iterator, long offset) {
-        return new SkippingIterator<E>(iterator, offset);
-    }
-
     // Unmodifiable
     //-----------------------------------------------------------------------
     /**
@@ -914,6 +899,68 @@ public class IteratorUtils {
         return PushbackIterator.pushbackIterator(iterator);
     }
 
+    // Skipping
+    //-----------------------------------------------------------------------
+    /**
+     * Decorates the specified iterator to skip the first N elements.
+     *
+     * @param <E>  the element type
+     * @param iterator  the iterator to decorate
+     * @param offset  the first number of elements to skip
+     * @return a new skipping iterator
+     * @throws IllegalArgumentException if the iterator is null or offset is negative
+     * @since 4.1
+     */
+    public static <E> SkippingIterator<E> skippingIterator(final Iterator<E> iterator, long offset) {
+        return new SkippingIterator<E>(iterator, offset);
+    }
+
+    // Zipping
+    //-----------------------------------------------------------------------
+    /**
+     * Returns an iterator that interleaves elements from the decorated iterators.
+     *
+     * @param <E>  the element type
+     * @param a  the first iterator to interleave
+     * @param b  the second iterator to interleave
+     * @return an iterator, interleaving the decorated iterators
+     * @throws IllegalArgumentException if any iterator is null
+     * @since 4.1
+     */
+    public static <E> ZippingIterator<E> zippingIterator(final Iterator<? extends E> a, final Iterator<? extends E> b) {
+        return new ZippingIterator<E>(a, b);
+    }
+
+    /**
+     * Returns an iterator that interleaves elements from the decorated iterators.
+     *
+     * @param <E>  the element type
+     * @param a  the first iterator to interleave
+     * @param b  the second iterator to interleave
+     * @param c  the third iterator to interleave 
+     * @return an iterator, interleaving the decorated iterators
+     * @throws IllegalArgumentException if any iterator is null
+     * @since 4.1
+     */
+    public static <E> ZippingIterator<E> zippingIterator(final Iterator<? extends E> a,
+                                                         final Iterator<? extends E> b,
+                                                         final Iterator<? extends E> c) {
+        return new ZippingIterator<E>(a, b, c);
+    }
+
+    /**
+     * Returns an iterator that interleaves elements from the decorated iterators.
+     *
+     * @param <E>  the element type
+     * @param iterators  the array of iterators to interleave
+     * @return an iterator, interleaving the decorated iterators
+     * @throws IllegalArgumentException if any iterator is null
+     * @since 4.1
+     */
+    public static <E> ZippingIterator<E> zippingIterator(final Iterator<? extends E>... iterators) {
+        return new ZippingIterator<E>(iterators);
+    }
+
     // Views
     //-----------------------------------------------------------------------
     /**

Modified: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/iterators/ZippingIterator.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/iterators/ZippingIterator.java?rev=1682196&r1=1682195&r2=1682196&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/iterators/ZippingIterator.java (original)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/iterators/ZippingIterator.java Thu May 28 09:58:09 2015
@@ -27,9 +27,9 @@ import org.apache.commons.collections4.F
  * Provides an interleaved iteration over the elements contained in a
  * collection of Iterators.
  * <p>
- * Given two {@link Iterator} instances <code>A</code> and
- * <code>B</code>, the {@link #next} method on this iterator will
- * alternate between <code>A.next()</code> and <code>B.next()</code>.
+ * Given two {@link Iterator} instances {@code A} and {@code B}, the
+ * {@link #next} method on this iterator will switch between {@code A.next()}
+ * and {@code B.next()} until both iterators are exhausted.
  *
  * @since 4.1
  * @version $Id$
@@ -38,8 +38,10 @@ public class ZippingIterator<E> implemen
 
     /** The {@link Iterator}s to evaluate. */
     private final Iterator<Iterator<? extends E>> iterators;
+
     /** The next iterator to use for next(). */
     private Iterator<? extends E> nextIterator = null;
+
     /** The last iterator which was used for next(). */
     private Iterator<? extends E> lastReturned = null;
 
@@ -50,8 +52,8 @@ public class ZippingIterator<E> implemen
      * Constructs a new <code>ZippingIterator</code> that will provide
      * interleaved iteration over the two given iterators.
      *
-     * @param a the first child iterator
-     * @param b the second child iterator
+     * @param a  the first child iterator
+     * @param b  the second child iterator
      * @throws NullPointerException if either iterator is null
      */
     @SuppressWarnings("unchecked")
@@ -60,19 +62,34 @@ public class ZippingIterator<E> implemen
     }
 
     /**
-     * Constructs a new <code>ZippingIterator</code> that will use the
-     * specified comparator to provide ordered iteration over the array of
-     * iterators.
+     * Constructs a new <code>ZippingIterator</code> that will provide
+     * interleaved iteration over the three given iterators.
+     *
+     * @param a  the first child iterator
+     * @param b  the second child iterator
+     * @param c  the third child iterator
+     * @throws NullPointerException if either iterator is null
+     */
+    @SuppressWarnings("unchecked")
+    public ZippingIterator(final Iterator<? extends E> a,
+                           final Iterator<? extends E> b,
+                           final Iterator<? extends E> c) {
+        this(new Iterator[] {a, b, c});
+    }
+
+    /**
+     * Constructs a new <code>ZippingIterator</code> that will provide
+     * interleaved iteration of the specified iterators.
      *
-     * @param iterators the array of iterators
-     * @throws NullPointerException if iterators array is or contains null
+     * @param iterators  the array of iterators
+     * @throws NullPointerException if any iterator is null
      */
     public ZippingIterator(final Iterator<? extends E>... iterators) {
-        // create a mutable list
+        // create a mutable list to be able to remove exhausted iterators
         final List<Iterator<? extends E>> list = new ArrayList<Iterator<? extends E>>();
-        for (Iterator<? extends E> iterator : iterators) {
+        for (final Iterator<? extends E> iterator : iterators) {
             if (iterator == null) {
-                throw new NullPointerException("Iterator must not be null");
+                throw new NullPointerException("Iterator must not be null.");
             }
             list.add(iterator);
         }
@@ -83,21 +100,21 @@ public class ZippingIterator<E> implemen
     // -------------------------------------------------------------------
 
     /**
-     * Returns <code>true</code> if any child iterator has remaining elements.
+     * Returns {@code true} if any child iterator has remaining elements.
      *
      * @return true if this iterator has remaining elements
      */
     public boolean hasNext() {
         // the next iterator has already been determined
-        // this might happen if hasNext() was called multiple
+        // this might happen if hasNext() is called multiple
         if (nextIterator != null) {
             return true;
         }
 
         while(iterators.hasNext()) {
-            final Iterator<? extends E> iterator = iterators.next();
-            if (iterator.hasNext()) {
-                nextIterator = iterator;
+            final Iterator<? extends E> childIterator = iterators.next();
+            if (childIterator.hasNext()) {
+                nextIterator = childIterator;
                 return true;
             } else {
                 // iterator is exhausted, remove it

Added: commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/iterators/ZippingIteratorTest.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/iterators/ZippingIteratorTest.java?rev=1682196&view=auto
==============================================================================
--- commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/iterators/ZippingIteratorTest.java (added)
+++ commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/iterators/ZippingIteratorTest.java Thu May 28 09:58:09 2015
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.collections4.iterators;
+
+import java.util.ArrayList;
+
+import org.apache.commons.collections4.IteratorUtils;
+
+/**
+ * Unit test suite for {@link ZippingIterator}.
+ *
+ * @version $Id$
+ */
+@SuppressWarnings("boxing")
+public class ZippingIteratorTest extends AbstractIteratorTest<Integer> {
+
+    //------------------------------------------------------------ Conventional
+
+    public ZippingIteratorTest(final String testName) {
+        super(testName);
+    }
+
+    //--------------------------------------------------------------- Lifecycle
+
+    private ArrayList<Integer> evens = null;
+    private ArrayList<Integer> odds = null;
+    private ArrayList<Integer> fib = null;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        evens = new ArrayList<Integer>();
+        odds = new ArrayList<Integer>();
+        for (int i = 0; i < 20; i++) {
+            if (0 == i % 2) {
+                evens.add(i);
+            } else {
+                odds.add(i);
+            }
+        }
+        fib = new ArrayList<Integer>();
+        fib.add(1);
+        fib.add(1);
+        fib.add(2);
+        fib.add(3);
+        fib.add(5);
+        fib.add(8);
+        fib.add(13);
+        fib.add(21);
+    }
+
+    //---------------------------------------------------- TestIterator Methods
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public ZippingIterator<Integer> makeEmptyIterator() {
+        return new ZippingIterator<Integer>(IteratorUtils.<Integer>emptyIterator());
+    }
+
+    @Override
+    public ZippingIterator<Integer> makeObject() {
+        return new ZippingIterator<Integer>(evens.iterator(), odds.iterator(), fib.iterator());
+    }
+
+    //------------------------------------------------------------------- Tests
+
+    public void testIterateEven() {
+        @SuppressWarnings("unchecked")
+        final ZippingIterator<Integer> iter = new ZippingIterator<Integer>(evens.iterator());
+        for (int i = 0; i < evens.size(); i++) {
+            assertTrue(iter.hasNext());
+            assertEquals(evens.get(i), iter.next());
+        }
+        assertTrue(!iter.hasNext());
+    }
+
+    public void testIterateEvenOdd() {
+        final ZippingIterator<Integer> iter = new ZippingIterator<Integer>(evens.iterator(), odds.iterator());
+        for (int i = 0; i < 20; i++) {
+            assertTrue(iter.hasNext());
+            assertEquals(Integer.valueOf(i), iter.next());
+        }
+        assertTrue(!iter.hasNext());
+    }
+
+    public void testIterateOddEven() {
+        final ZippingIterator<Integer> iter = new ZippingIterator<Integer>(odds.iterator(), evens.iterator());
+        for (int i = 0, j = 0; i < 20; i++) {
+            assertTrue(iter.hasNext());
+            int val = iter.next();
+            if (i % 2 == 0) {
+                assertEquals(odds.get(j).intValue(), val);
+            } else {
+                assertEquals(evens.get(j).intValue(), val);
+                j++;
+            }
+        }
+        assertTrue(!iter.hasNext());
+    }
+
+    public void testIterateEvenEven() {
+        final ZippingIterator<Integer> iter = new ZippingIterator<Integer>(evens.iterator(), evens.iterator());
+        for (int i = 0; i < evens.size(); i++) {
+            assertTrue(iter.hasNext());
+            assertEquals(evens.get(i), iter.next());
+            assertTrue(iter.hasNext());
+            assertEquals(evens.get(i), iter.next());
+        }
+        assertTrue(!iter.hasNext());
+    }
+
+    public void testIterateFibEvenOdd() {
+        final ZippingIterator<Integer> iter = new ZippingIterator<Integer>(fib.iterator(), evens.iterator(), odds.iterator());
+
+        assertEquals(Integer.valueOf(1),iter.next());  // fib    1
+        assertEquals(Integer.valueOf(0),iter.next());  // even   0
+        assertEquals(Integer.valueOf(1),iter.next());  // odd    1
+        assertEquals(Integer.valueOf(1),iter.next());  // fib    1
+        assertEquals(Integer.valueOf(2),iter.next());  // even   2
+        assertEquals(Integer.valueOf(3),iter.next());  // odd    3
+        assertEquals(Integer.valueOf(2),iter.next());  // fib    2
+        assertEquals(Integer.valueOf(4),iter.next());  // even   4
+        assertEquals(Integer.valueOf(5),iter.next());  // odd    5
+        assertEquals(Integer.valueOf(3),iter.next());  // fib    3
+        assertEquals(Integer.valueOf(6),iter.next());  // even   6
+        assertEquals(Integer.valueOf(7),iter.next());  // odd    7
+        assertEquals(Integer.valueOf(5),iter.next());  // fib    5
+        assertEquals(Integer.valueOf(8),iter.next());  // even   8
+        assertEquals(Integer.valueOf(9),iter.next());  // odd    9
+        assertEquals(Integer.valueOf(8),iter.next());  // fib    8
+        assertEquals(Integer.valueOf(10),iter.next()); // even  10
+        assertEquals(Integer.valueOf(11),iter.next()); // odd   11
+        assertEquals(Integer.valueOf(13),iter.next()); // fib   13
+        assertEquals(Integer.valueOf(12),iter.next()); // even  12
+        assertEquals(Integer.valueOf(13),iter.next()); // odd   13
+        assertEquals(Integer.valueOf(21),iter.next()); // fib   21
+        assertEquals(Integer.valueOf(14),iter.next()); // even  14
+        assertEquals(Integer.valueOf(15),iter.next()); // odd   15
+        assertEquals(Integer.valueOf(16),iter.next()); // even  16
+        assertEquals(Integer.valueOf(17),iter.next()); // odd   17
+        assertEquals(Integer.valueOf(18),iter.next()); // even  18
+        assertEquals(Integer.valueOf(19),iter.next()); // odd   19
+
+        assertTrue(!iter.hasNext());
+    }
+
+    public void testRemoveFromSingle() {
+        @SuppressWarnings("unchecked")
+        final ZippingIterator<Integer> iter = new ZippingIterator<Integer>(evens.iterator());
+        int expectedSize = evens.size();
+        while (iter.hasNext()) {
+            final Object o = iter.next();
+            final Integer val = (Integer) o;
+            if (val.intValue() % 4 == 0) {
+                expectedSize--;
+                iter.remove();
+            }
+        }
+        assertEquals(expectedSize, evens.size());
+    }
+
+    public void testRemoveFromDouble() {
+        final ZippingIterator<Integer> iter = new ZippingIterator<Integer>(evens.iterator(), odds.iterator());
+        int expectedSize = evens.size() + odds.size();
+        while (iter.hasNext()) {
+            final Object o = iter.next();
+            final Integer val = (Integer) o;
+            if (val.intValue() % 4 == 0 || val.intValue() % 3 == 0) {
+                expectedSize--;
+                iter.remove();
+            }
+        }
+        assertEquals(expectedSize, evens.size() + odds.size());
+    }
+
+}
+

Propchange: commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/iterators/ZippingIteratorTest.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision HeadURL