package fr.pandacube.lib.util; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.NoSuchElementException; /** * An {@link Iterator} that iterate over all the elements of all the provided iterators. * In other words, this class concatenate the provided iterators. * @param the type of the values in the iterators */ public class IteratorIterator implements Iterator { /** * Create an {@link IteratorIterator} with the provided {@link Collection} of {@link Iterable}. * The iterables’ iterators will be concatenated in the order of the collection’s iterator. * @param coll the collection of iterables. * @return a new instance of {@link IteratorIterator} iterating over the elements of the provided iterables. * @param the type of the values in the iterables. */ public static IteratorIterator ofCollectionOfIterable(Collection> coll) { return new IteratorIterator<>(coll.stream().map(Iterable::iterator).iterator()); } /** * Create an {@link IteratorIterator} with the provided {@link Collection} of {@link Iterator}. * The iterators will be concatenated in the order of the collection’s iterator. * @param coll the collection of iterators. * @return a new instance of {@link IteratorIterator} iterating over the elements of the provided iterators. * @param the type of the values in the iterators. */ public static IteratorIterator ofCollectionOfIterator(Collection> coll) { return new IteratorIterator<>(new ArrayList<>(coll).iterator()); } /** * Create an {@link IteratorIterator} with the provided array of {@link Iterable}. * The iterables’ iterators will be concatenated in the order of the array. * @param arr the array of iterables. * @return a new instance of {@link IteratorIterator} iterating over the elements of the provided iterables. * @param the type of the values in the iterables. */ @SafeVarargs public static IteratorIterator ofArrayOfIterable(Iterable... arr) { return new IteratorIterator<>(Arrays.stream(arr).map(Iterable::iterator).iterator()); } /** * Create an {@link IteratorIterator} with the provided array of {@link Iterator}. * The iterators will be concatenated in the order of the array. * @param arr the array of iterators. * @return a new instance of {@link IteratorIterator} iterating over the elements of the provided iterators. * @param the type of the values in the iterators. */ @SafeVarargs public static IteratorIterator ofArrayOfIterator(Iterator... arr) { return new IteratorIterator<>(Arrays.asList(arr).iterator()); } private final Iterator> iterators; private Iterator currentValueIterator = null; private Iterator nextValueIterator = null; private IteratorIterator(Iterator> iterators) { this.iterators = iterators; } private void fixNextIterator() { if (nextValueIterator != null && !nextValueIterator.hasNext()) { nextValueIterator = null; } } private void fixState() { fixNextIterator(); while (nextValueIterator == null && iterators.hasNext()) { nextValueIterator = iterators.next(); fixNextIterator(); } } @Override public boolean hasNext() { fixState(); return nextValueIterator != null && nextValueIterator.hasNext(); } @Override public T next() { if (!hasNext()) throw new NoSuchElementException("No next value found in iterator."); currentValueIterator = nextValueIterator; return currentValueIterator.next(); } @Override public void remove() { if (currentValueIterator == null) throw new IllegalStateException(); currentValueIterator.remove(); } }