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 extends Iterator extends E>> iterators) {
+ return new LazyIteratorChain() {
+
+ @Override
+ protected Iterator extends E> 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(...)
*/