diff --git a/src/changes/changes.xml b/src/changes/changes.xml index b2dde9c3d..eed23d6da 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -51,6 +51,8 @@ Add missing methods in AbstractMapTests. Add ConcurrentReferenceHashMap. Add commons.easymock.version to parameterize EasyMock version. + Add org.apache.commons.collections4.IteratorUtils.chainedIterator(Iterator<? extends Iterator<? extends E>>). + Update bloom filter documentation #508. Bump commons-codec:commons-codec from 1.17.0 to 1.17.1 #514. diff --git a/src/main/java/org/apache/commons/collections4/IteratorUtils.java b/src/main/java/org/apache/commons/collections4/IteratorUtils.java index 75fcaf5ae..ac21499be 100644 --- a/src/main/java/org/apache/commons/collections4/IteratorUtils.java +++ b/src/main/java/org/apache/commons/collections4/IteratorUtils.java @@ -46,6 +46,7 @@ import org.apache.commons.collections4.iterators.FilterListIterator; import org.apache.commons.collections4.iterators.IteratorChain; import org.apache.commons.collections4.iterators.IteratorEnumeration; import org.apache.commons.collections4.iterators.IteratorIterable; +import org.apache.commons.collections4.iterators.LazyIteratorChain; import org.apache.commons.collections4.iterators.ListIteratorWrapper; import org.apache.commons.collections4.iterators.LoopingIterator; import org.apache.commons.collections4.iterators.LoopingListIterator; @@ -426,6 +427,27 @@ public class IteratorUtils { return new IteratorChain<>(iterators); } + /** + * Gets an iterator that iterates through an {@link Iterator} of Iterators one after another. + * + * @param the element type + * @param iterators the iterators to use, not null or empty or contain nulls + * @return a combination iterator over the iterators + * @throws NullPointerException if iterators collection is null or contains a null + * @throws ClassCastException if the iterators collection contains the wrong object type + * @since 4.5.0-M3 + */ + public static Iterator chainedIterator(final Iterator> iterators) { + return new LazyIteratorChain() { + + @Override + protected Iterator nextIterator(final int count) { + return iterators.hasNext() ? iterators.next() : null; + } + + }; + } + /** * Gets an iterator that iterates through an array of {@link Iterator}s * one after another. diff --git a/src/test/java/org/apache/commons/collections4/IteratorUtilsTest.java b/src/test/java/org/apache/commons/collections4/IteratorUtilsTest.java index 05e2347c8..820a70b29 100644 --- a/src/test/java/org/apache/commons/collections4/IteratorUtilsTest.java +++ b/src/test/java/org/apache/commons/collections4/IteratorUtilsTest.java @@ -435,6 +435,26 @@ public class IteratorUtilsTest { "Expecting NullPointerException"); } + @Test + public void testChainedIteratorArrayOfIterator() { + // String + final IteratorChainTest iteratorChainTest = new IteratorChainTest(); + iteratorChainTest.setUp(); + // @formateter:off + final Iterator iterator = IteratorUtils.chainedIterator( + iteratorChainTest.getList1().iterator(), + iteratorChainTest.getList2().iterator(), + iteratorChainTest.getList3().iterator()); + // @formateter:on + assertEquals("One", iterator.next()); + assertEquals("Two", iterator.next()); + assertEquals("Three", iterator.next()); + assertEquals("Four", iterator.next()); + assertEquals("Five", iterator.next()); + assertEquals("Six", iterator.next()); + assertFalse(iterator.hasNext()); + } + @Test public void testChainedIteratorList() { final IteratorChainTest iteratorChainTest = new IteratorChainTest(); @@ -452,6 +472,33 @@ public class IteratorUtilsTest { assertEquals(actual, expected); } + @Test + public void testChainedIteratorOfIterators() { + final List> lst = new ArrayList<>(); + final List iList = Arrays.asList(1, 3); + lst.add(Arrays.asList(3.14f, Math.sqrt(2.0))); + final Iterator> toBeUnwound = new Iterator>() { + List> lst = Arrays.asList(Arrays.asList(1, 3), Arrays.asList(3.14F, Math.sqrt(2.0))); + Iterator> lstIter = lst.iterator(); + + @Override + public boolean hasNext() { + return lstIter.hasNext(); + } + + @Override + public Iterator next() { + return lstIter.next().iterator(); + } + }; + + final List expected = Arrays.asList(1, 3, 3.14f, Math.sqrt(2.0)); + final Iterator iter = IteratorUtils.chainedIterator(toBeUnwound); + final List actual = new ArrayList<>(); + iter.forEachRemaining(actual::add); + assertEquals(actual, expected); + } + @Test public void testChainedIteratorRawGenerics() { final ArrayList arrayList = new ArrayList(); @@ -461,26 +508,6 @@ public class IteratorUtilsTest { assertTrue(IteratorUtils.chainedIterator(coll) instanceof Iterator, "create instance fail"); } - @Test - public void testChainedIteratorString() { - // String - final IteratorChainTest iteratorChainTest = new IteratorChainTest(); - iteratorChainTest.setUp(); - // @formateter:off - final Iterator iterator = IteratorUtils.chainedIterator( - iteratorChainTest.getList1().iterator(), - iteratorChainTest.getList2().iterator(), - iteratorChainTest.getList3().iterator()); - // @formateter:on - assertEquals("One", iterator.next()); - assertEquals("Two", iterator.next()); - assertEquals("Three", iterator.next()); - assertEquals("Four", iterator.next()); - assertEquals("Five", iterator.next()); - assertEquals("Six", iterator.next()); - assertFalse(iterator.hasNext()); - } - /** * Tests methods collatedIterator(...) */