Skip to content

Commit

Permalink
[COLLECTIONS-869] Add
Browse files Browse the repository at this point in the history
org.apache.commons.collections4.IteratorUtils.chainedIterator(Iterator<?
extends Iterator<? extends E>>)
  • Loading branch information
garydgregory committed Oct 19, 2024
1 parent 74e207e commit c8cd99e
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 20 deletions.
2 changes: 2 additions & 0 deletions src/changes/changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
<action type="add" dev="ggregory" due-to="Gary Gregory">Add missing methods in AbstractMapTests.</action>
<action type="add" issue="COLLECTIONS-700" dev="ggregory" due-to="Gary Gregory">Add ConcurrentReferenceHashMap.</action>
<action type="add" dev="ggregory" due-to="Gary Gregory">Add commons.easymock.version to parameterize EasyMock version.</action>
<action type="add" issue="COLLECTIONS-869" dev="ggregory" due-to="Gary Gregory">Add org.apache.commons.collections4.IteratorUtils.chainedIterator(Iterator&lt;? extends Iterator&lt;? extends E&gt;&gt;).</action>

<!-- UPDATE -->
<action type="update" issue="COLLECTIONS-857" dev="ggregory" due-to="Claude Warren">Update bloom filter documentation #508.</action>
<action type="update" dev="ggregory" due-to="Dependabot, Gary Gregory">Bump commons-codec:commons-codec from 1.17.0 to 1.17.1 #514.</action>
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/org/apache/commons/collections4/IteratorUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
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;
Expand Down Expand Up @@ -426,6 +427,27 @@ public static <E> Iterator<E> chainedIterator(final Collection<? extends Iterato
return new IteratorChain<>(iterators);
}

/**
* Gets an iterator that iterates through an {@link Iterator} of Iterators one after another.
*
* @param <E> 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 <E> Iterator<E> chainedIterator(final Iterator<? extends Iterator<? extends E>> iterators) {
return new LazyIteratorChain<E>() {

@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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,26 @@ public void testAsMultipleIterableNull() {
"Expecting NullPointerException");
}

@Test
public void testChainedIteratorArrayOfIterator() {
// String
final IteratorChainTest iteratorChainTest = new IteratorChainTest();
iteratorChainTest.setUp();
// @formateter:off
final Iterator<String> 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();
Expand All @@ -452,6 +472,33 @@ public void testChainedIteratorList() {
assertEquals(actual, expected);
}

@Test
public void testChainedIteratorOfIterators() {
final List<List<Number>> lst = new ArrayList<>();
final List<Integer> iList = Arrays.asList(1, 3);
lst.add(Arrays.asList(3.14f, Math.sqrt(2.0)));
final Iterator<Iterator<Number>> toBeUnwound = new Iterator<Iterator<Number>>() {
List<List<Number>> lst = Arrays.asList(Arrays.asList(1, 3), Arrays.asList(3.14F, Math.sqrt(2.0)));
Iterator<List<Number>> lstIter = lst.iterator();

@Override
public boolean hasNext() {
return lstIter.hasNext();
}

@Override
public Iterator<Number> next() {
return lstIter.next().iterator();
}
};

final List<Number> expected = Arrays.asList(1, 3, 3.14f, Math.sqrt(2.0));
final Iterator<Number> iter = IteratorUtils.chainedIterator(toBeUnwound);
final List<Number> actual = new ArrayList<>();
iter.forEachRemaining(actual::add);
assertEquals(actual, expected);
}

@Test
public void testChainedIteratorRawGenerics() {
final ArrayList arrayList = new ArrayList();
Expand All @@ -461,26 +508,6 @@ public void testChainedIteratorRawGenerics() {
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<String> 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(...)
*/
Expand Down

0 comments on commit c8cd99e

Please sign in to comment.