2022-07-20 13:18:57 +02:00
|
|
|
|
package fr.pandacube.lib.util;
|
2021-08-23 02:24:34 +02:00
|
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
import java.util.Collection;
|
|
|
|
|
import java.util.Iterator;
|
|
|
|
|
import java.util.NoSuchElementException;
|
|
|
|
|
|
2022-07-28 01:13:35 +02:00
|
|
|
|
/**
|
|
|
|
|
* An {@link Iterator} that iterate over all the elements of all the provided iterators.
|
|
|
|
|
* In other words, this class concatenate the provided iterators.
|
|
|
|
|
* @param <T> the type of the values in the iterators
|
|
|
|
|
*/
|
2021-08-23 02:24:34 +02:00
|
|
|
|
public class IteratorIterator<T> implements Iterator<T> {
|
|
|
|
|
|
2022-07-28 01:13:35 +02:00
|
|
|
|
/**
|
|
|
|
|
* 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 <T> the type of the values in the iterables.
|
|
|
|
|
*/
|
2021-08-23 02:24:34 +02:00
|
|
|
|
public static <T> IteratorIterator<T> ofCollectionOfIterable(Collection<Iterable<T>> coll) {
|
2022-07-10 00:55:56 +02:00
|
|
|
|
return new IteratorIterator<>(coll.stream().map(Iterable::iterator).iterator());
|
2021-08-23 02:24:34 +02:00
|
|
|
|
}
|
2022-07-28 01:13:35 +02:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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 <T> the type of the values in the iterators.
|
|
|
|
|
*/
|
2021-08-23 02:24:34 +02:00
|
|
|
|
public static <T> IteratorIterator<T> ofCollectionOfIterator(Collection<Iterator<T>> coll) {
|
|
|
|
|
return new IteratorIterator<>(new ArrayList<>(coll).iterator());
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-28 01:13:35 +02:00
|
|
|
|
/**
|
|
|
|
|
* 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 <T> the type of the values in the iterables.
|
|
|
|
|
*/
|
2021-08-23 02:24:34 +02:00
|
|
|
|
@SafeVarargs
|
|
|
|
|
public static <T> IteratorIterator<T> ofArrayOfIterable(Iterable<T>... arr) {
|
2022-07-10 00:55:56 +02:00
|
|
|
|
return new IteratorIterator<>(Arrays.stream(arr).map(Iterable::iterator).iterator());
|
2021-08-23 02:24:34 +02:00
|
|
|
|
}
|
2022-07-28 01:13:35 +02:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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 <T> the type of the values in the iterators.
|
|
|
|
|
*/
|
2021-08-23 02:24:34 +02:00
|
|
|
|
@SafeVarargs
|
|
|
|
|
public static <T> IteratorIterator<T> ofArrayOfIterator(Iterator<T>... arr) {
|
|
|
|
|
return new IteratorIterator<>(Arrays.asList(arr).iterator());
|
|
|
|
|
}
|
2022-07-28 01:13:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-07-10 00:55:56 +02:00
|
|
|
|
private final Iterator<Iterator<T>> iterators;
|
2022-07-28 01:13:35 +02:00
|
|
|
|
|
|
|
|
|
private Iterator<T> currentValueIterator = null;
|
|
|
|
|
private Iterator<T> nextValueIterator = null;
|
2021-08-23 02:24:34 +02:00
|
|
|
|
|
|
|
|
|
private IteratorIterator(Iterator<Iterator<T>> iterators) {
|
|
|
|
|
this.iterators = iterators;
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-28 01:13:35 +02:00
|
|
|
|
private void fixNextIterator() {
|
|
|
|
|
if (nextValueIterator != null && !nextValueIterator.hasNext()) {
|
|
|
|
|
nextValueIterator = null;
|
2021-08-23 02:24:34 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private void fixState() {
|
2022-07-28 01:13:35 +02:00
|
|
|
|
fixNextIterator();
|
|
|
|
|
while (nextValueIterator == null && iterators.hasNext()) {
|
|
|
|
|
nextValueIterator = iterators.next();
|
|
|
|
|
fixNextIterator();
|
2021-08-23 02:24:34 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-07-28 01:13:35 +02:00
|
|
|
|
|
2021-08-23 02:24:34 +02:00
|
|
|
|
@Override
|
|
|
|
|
public boolean hasNext() {
|
|
|
|
|
fixState();
|
2022-07-28 01:13:35 +02:00
|
|
|
|
return nextValueIterator != null && nextValueIterator.hasNext();
|
2021-08-23 02:24:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public T next() {
|
|
|
|
|
if (!hasNext())
|
|
|
|
|
throw new NoSuchElementException("No next value found in iterator.");
|
2022-07-28 01:13:35 +02:00
|
|
|
|
currentValueIterator = nextValueIterator;
|
|
|
|
|
return currentValueIterator.next();
|
2021-08-23 02:24:34 +02:00
|
|
|
|
}
|
2022-07-10 00:55:56 +02:00
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void remove() {
|
2022-07-28 01:13:35 +02:00
|
|
|
|
if (currentValueIterator == null)
|
|
|
|
|
throw new IllegalStateException();
|
|
|
|
|
currentValueIterator.remove();
|
2022-07-10 00:55:56 +02:00
|
|
|
|
}
|
2021-08-23 02:24:34 +02:00
|
|
|
|
}
|