/* __ __ __ __ __ ___
* \ \ / / \ \ / / __/
* \ \/ / /\ \ \/ / /
* \____/__/ \__\____/__/.ɪᴏ
* ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ
*/
package io.vavr.collection;
import io.vavr.*;
import io.vavr.collection.IteratorModule.ConcatIterator;
import io.vavr.collection.IteratorModule.DistinctIterator;
import io.vavr.collection.IteratorModule.GroupedIterator;
import io.vavr.control.Option;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.*;
import static java.lang.Double.NEGATIVE_INFINITY;
import static java.lang.Double.POSITIVE_INFINITY;
import static java.math.RoundingMode.HALF_UP;
import static io.vavr.collection.IteratorModule.BigDecimalHelper.areEqual;
import static io.vavr.collection.IteratorModule.BigDecimalHelper.asDecimal;
import static io.vavr.collection.IteratorModule.EmptyIterator;
/**
* {@code io.vavr.collection.Iterator} is a compositional replacement for {@code java.util.Iterator}
* whose purpose is to iterate <em>once</em> over a sequence of elements.
* <p>
* It is recommended to create instances using {@link AbstractIterator} in favor of {@code Iterator}.
* <p>
* <strong>Note:</strong> Iterators encapsulate mutable state.
* They are not meant to be used concurrently by different threads. Do not reuse Iterators, e.g. after passing to
* {@linkplain io.vavr.collection.List#ofAll(Iterable)}.
* <p>
* There are two abstract methods: {@code hasNext} for checking if there is a next element available,
* and {@code next} which removes the next element from the iterator and returns it. They can be called
* an arbitrary amount of times. If {@code hasNext} returns false, a call of {@code next} will throw
* a {@code NoSuchElementException}.
* <p>
* <strong>Caution: Other methods than {@code hasNext} and {@code next} can be called only once (exclusively).
* More specifically, after calling a method it cannot be guaranteed that the next call will succeed.</strong>
* <p>
* An Iterator that can be only used once because it is a traversal pointer into a collection, and not a collection
* itself.
*
* @param <T> Component type
* @author Daniel Dietrich
*/
// DEV-NOTE: we prefer returning empty() over this if !hasNext() == true in order to free memory.
public interface Iterator<T> extends java.util.Iterator<T>, Traversable<T> {
/**
* Creates an Iterator which traverses along the concatenation of the given iterables.
*
* @param iterables The iterables
* @param <T> Component type.
* @return A new {@code io.vavr.collection.Iterator}
*/
@SuppressWarnings("varargs")
@SafeVarargs
static <T> Iterator<T> concat(Iterable<? extends T>... iterables) {
Objects.requireNonNull(iterables, "iterables is null");
if (iterables.length == 0) {
return empty();
} else {
return new ConcatIterator<>(Stream.of(iterables).map(Iterator::ofAll).iterator());
}
}
/**
* Creates an Iterator which traverses along the concatenation of the given iterables.
*
* @param iterables The iterable of iterables
* @param <T> Component type.
* @return A new {@code io.vavr.collection.Iterator}
*/
static <T> Iterator<T> concat(Iterable<? extends Iterable<? extends T>> iterables) {
Objects.requireNonNull(iterables, "iterables is null");
if (!iterables.iterator().hasNext()) {
return empty();
} else {
return new ConcatIterator<>(Stream.ofAll(iterables).map(Iterator::ofAll).iterator());
}
}
/**
* Returns the empty Iterator.
*
* @param <T> Component type
* @return The empty Iterator
*/
@SuppressWarnings("unchecked")
static <T> Iterator<T> empty() {
return (Iterator<T>) EmptyIterator.INSTANCE;
}
/**
* Narrows a widened {@code Iterator<? extends T>} to {@code Iterator<T>}
* by performing a type-safe cast. This is eligible because immutable/read-only
* collections are covariant.
*
* @param iterator An {@code Iterator}.
* @param <T> Component type of the {@code Iterator}.
* @return the given {@code iterator} instance as narrowed type {@code Iterator<T>}.
*/
@SuppressWarnings("unchecked")
static <T> Iterator<T> narrow(Iterator<? extends T> iterator) {
return (Iterator<T>) iterator;
}
/**
* Creates an Iterator which traverses one element.
*
* @param element An element
* @param <T> Component type.
* @return A new Iterator
*/
static <T> Iterator<T> of(T element) {
return new AbstractIterator<T>() {
boolean hasNext = true;
@Override
public boolean hasNext() {
return hasNext;
}
@Override
public T getNext() {
hasNext = false;
return element;
}
};
}
/**
* Creates an Iterator which traverses the given elements.
*
* @param elements Zero or more elements
* @param <T> Component type
* @return A new Iterator
*/
@SafeVarargs
static <T> Iterator<T> of(T... elements) {
Objects.requireNonNull(elements, "elements is null");
if (elements.length == 0) {
return empty();
} else {
return new AbstractIterator<T>() {
int index = 0;
@Override
public boolean hasNext() {
return index < elements.length;
}
@Override
public T getNext() {
return elements[index++];
}
};
}
}
/**
* Creates an Iterator based on the given Iterable. This is a convenience method for
* {@code Iterator.ofAll(iterable.iterator()}.
*
* @param iterable A {@link Iterable}
* @param <T> Component type.
* @return A new {@code io.vavr.collection.Iterator}
*/
@SuppressWarnings("unchecked")
static <T> Iterator<T> ofAll(Iterable<? extends T> iterable) {
Objects.requireNonNull(iterable, "iterable is null");
if (iterable instanceof Iterator) {
return (Iterator<T>) iterable;
} else {
return ofAll(iterable.iterator());
}
}
/**
* Creates an Iterator based on the given Iterator by
* delegating calls of {@code hasNext()} and {@code next()} to it.
*
* @param iterator A {@link java.util.Iterator}
* @param <T> Component type.
* @return A new {@code io.vavr.collection.Iterator}
*/
@SuppressWarnings("unchecked")
static <T> Iterator<T> ofAll(java.util.Iterator<? extends T> iterator) {
Objects.requireNonNull(iterator, "iterator is null");
if (iterator instanceof Iterator) {
return (Iterator<T>) iterator;
} else {
return new AbstractIterator<T>() {
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public T getNext() {
return iterator.next();
}
};
}
}
/**
* Creates an Iterator from boolean values.
*
* @param elements boolean values
* @return A new Iterator of Boolean values
* @throws NullPointerException if elements is null
*/
static Iterator<Boolean> ofAll(boolean... elements) {
Objects.requireNonNull(elements, "elements is null");
return new AbstractIterator<Boolean>() {
int i = 0;
@Override
public boolean hasNext() {
return i < elements.length;
}
@Override
public Boolean getNext() {
return elements[i++];
}
};
}
/**
* Creates an Iterator from byte values.
*
* @param elements byte values
* @return A new Iterator of Byte values
* @throws NullPointerException if elements is null
*/
static Iterator<Byte> ofAll(byte... elements) {
Objects.requireNonNull(elements, "elements is null");
return new AbstractIterator<Byte>() {
int i = 0;
@Override
public boolean hasNext() {
return i < elements.length;
}
@Override
public Byte getNext() {
return elements[i++];
}
};
}
/**
* Creates an Iterator from char values.
*
* @param elements char values
* @return A new Iterator of Character values
* @throws NullPointerException if elements is null
*/
static Iterator<Character> ofAll(char... elements) {
Objects.requireNonNull(elements, "elements is null");
return new AbstractIterator<Character>() {
int i = 0;
@Override
public boolean hasNext() {
return i < elements.length;
}
@Override
public Character getNext() {
return elements[i++];
}
};
}
/**
* Creates ann Iterator from double values.
*
* @param elements double values
* @return A new Iterator of Double values
* @throws NullPointerException if elements is null
*/
static Iterator<Double> ofAll(double... elements) {
Objects.requireNonNull(elements, "elements is null");
return new AbstractIterator<Double>() {
int i = 0;
@Override
public boolean hasNext() {
return i < elements.length;
}
@Override
public Double getNext() {
return elements[i++];
}
};
}
/**
* Creates an Iterator from float values.
*
* @param elements float values
* @return A new Iterator of Float values
* @throws NullPointerException if elements is null
*/
static Iterator<Float> ofAll(float... elements) {
Objects.requireNonNull(elements, "elements is null");
return new AbstractIterator<Float>() {
int i = 0;
@Override
public boolean hasNext() {
return i < elements.length;
}
@Override
public Float getNext() {
return elements[i++];
}
};
}
/**
* Creates an Iterator from int values.
*
* @param elements int values
* @return A new Iterator of Integer values
* @throws NullPointerException if elements is null
*/
static Iterator<Integer> ofAll(int... elements) {
Objects.requireNonNull(elements, "elements is null");
return new AbstractIterator<Integer>() {
int i = 0;
@Override
public boolean hasNext() {
return i < elements.length;
}
@Override
public Integer getNext() {
return elements[i++];
}
};
}
/**
* Creates an Iterator from long values.
*
* @param elements long values
* @return A new Iterator of Long values
* @throws NullPointerException if elements is null
*/
static Iterator<Long> ofAll(long... elements) {
Objects.requireNonNull(elements, "elements is null");
return new AbstractIterator<Long>() {
int i = 0;
@Override
public boolean hasNext() {
return i < elements.length;
}
@Override
public Long getNext() {
return elements[i++];
}
};
}
/**
* Creates an Iterator from short values.
*
* @param elements short values
* @return A new Iterator of Short values
* @throws NullPointerException if elements is null
*/
static Iterator<Short> ofAll(short... elements) {
Objects.requireNonNull(elements, "elements is null");
return new AbstractIterator<Short>() {
int i = 0;
@Override
public boolean hasNext() {
return i < elements.length;
}
@Override
public Short getNext() {
return elements[i++];
}
};
}
/**
* Returns an Iterator on a sequence of {@code n} values of a given Function {@code f}
* over a range of integer values from 0 to {@code n - 1}.
*
* @param <T> Component type of the Iterator
* @param n The number of elements
* @param f The Function computing element values
* @return An Iterator on a sequence of elements {@code f(0),f(1), ..., f(n - 1)}
* @throws NullPointerException if {@code f} is null
*/
static <T> Iterator<T> tabulate(int n, Function<? super Integer, ? extends T> f) {
Objects.requireNonNull(f, "f is null");
return io.vavr.collection.Collections.tabulate(n, f);
}
/**
* Returns an Iterator on a sequence of {@code n} values supplied by a given Supplier {@code s}.
*
* @param <T> Component type of the Iterator
* @param n The number of elements
* @param s The Supplier computing element values
* @return An iterator on a sequence of {@code n} elements, where each element contains the result supplied by {@code s}.
* @throws NullPointerException if {@code s} is null
*/
static <T> Iterator<T> fill(int n, Supplier<? extends T> s) {
Objects.requireNonNull(s, "s is null");
return io.vavr.collection.Collections.fill(n, s);
}
/**
* Creates an Iterator of characters starting from {@code from}, extending to {@code toExclusive - 1}.
* <p>
* Examples:
* <pre>
* <code>
* Iterator.range('a', 'c') // = ('a', 'b')
* Iterator.range('c', 'a') // = ()
* </code>
* </pre>
*
* @param from the first character
* @param toExclusive the successor of the last character
* @return a range of characters as specified or the empty range if {@code from >= toExclusive}
*/
static Iterator<Character> range(char from, char toExclusive) {
return rangeBy(from, toExclusive, 1);
}
/**
* Creates an Iterator of characters starting from {@code from}, extending to {@code toExclusive - 1},
* with {@code step}.
* <p>
* Examples:
* <pre>
* <code>
* Iterator.rangeBy('a', 'c', 1) // = ('a', 'b')
* Iterator.rangeBy('a', 'd', 2) // = ('a', 'c')
* Iterator.rangeBy('d', 'a', -2) // = ('d', 'b')
* Iterator.rangeBy('d', 'a', 2) // = ()
* </code>
* </pre>
*
* @param from the first character
* @param toExclusive the successor of the last character if step > 0, the predecessor of the last character if step < 0
* @param step the step
* @return a range of characters as specified or the empty range if {@code signum(step) == signum(from - toExclusive)}.
* @throws IllegalArgumentException if {@code step} is zero
*/
static Iterator<Character> rangeBy(char from, char toExclusive, int step) {
return rangeBy((int) from, (int) toExclusive, step).map(i -> (char) i.shortValue());
}
@GwtIncompatible("BigDecimalHelper is GwtIncompatible")
static Iterator<Double> rangeBy(double from, double toExclusive, double step) {
final BigDecimal fromDecimal = asDecimal(from), toDecimal = asDecimal(toExclusive), stepDecimal = asDecimal(step);
return rangeBy(fromDecimal, toDecimal, stepDecimal).map(BigDecimal::doubleValue);
}
static Iterator<BigDecimal> rangeBy(BigDecimal from, BigDecimal toExclusive, BigDecimal step) {
if (step.signum() == 0) {
throw new IllegalArgumentException("step cannot be 0");
} else if (areEqual(from, toExclusive) || step.signum() == from.subtract(toExclusive).signum()) {
return empty();
} else {
if (step.signum() > 0) {
return new AbstractIterator<BigDecimal>() {
BigDecimal i = from;
@Override
public boolean hasNext() {
return i.compareTo(toExclusive) < 0;
}
@Override
public BigDecimal getNext() {
final BigDecimal next = this.i;
this.i = next.add(step);
return next;
}
};
} else {
return new AbstractIterator<BigDecimal>() {
BigDecimal i = from;
@Override
public boolean hasNext() {
return i.compareTo(toExclusive) > 0;
}
@Override
public BigDecimal getNext() {
final BigDecimal next = this.i;
this.i = next.add(step);
return next;
}
};
}
}
}
/**
* Creates an Iterator of int numbers starting from {@code from}, extending to {@code toExclusive - 1}.
* <p>
* Examples:
* <pre>
* <code>
* Iterator.range(0, 0) // = ()
* Iterator.range(2, 0) // = ()
* Iterator.range(-2, 2) // = (-2, -1, 0, 1)
* </code>
* </pre>
*
* @param from the first number
* @param toExclusive the last number + 1
* @return a range of int values as specified or the empty range if {@code from >= toExclusive}
*/
static Iterator<Integer> range(int from, int toExclusive) {
return rangeBy(from, toExclusive, 1);
}
/**
* Creates an Iterator of int numbers starting from {@code from}, extending to {@code toExclusive - 1},
* with {@code step}.
* <p>
* Examples:
* <pre>
* <code>
* Iterator.rangeBy(1, 3, 1) // = (1, 2)
* Iterator.rangeBy(1, 4, 2) // = (1, 3)
* Iterator.rangeBy(4, 1, -2) // = (4, 2)
* Iterator.rangeBy(4, 1, 2) // = ()
* </code>
* </pre>
*
* @param from the first number
* @param toExclusive the last number + 1 if step > 0, the last number - 1 if step < 0
* @param step the step
* @return a range of long values as specified or the empty range if {@code (from == toExclusive) || (step * (from - toExclusive) > 0)}.
* @throws IllegalArgumentException if {@code step} is zero
*/
static Iterator<Integer> rangeBy(int from, int toExclusive, int step) {
final int toInclusive = toExclusive - (step > 0 ? 1 : -1);
return rangeClosedBy(from, toInclusive, step);
}
/**
* Creates an Iterator of long numbers starting from {@code from}, extending to {@code toExclusive - 1}.
* <p>
* Examples:
* <pre>
* <code>
* Iterator.range(0L, 0L) // = ()
* Iterator.range(2L, 0L) // = ()
* Iterator.range(-2L, 2L) // = (-2L, -1L, 0L, 1L)
* </code>
* </pre>
*
* @param from the first number
* @param toExclusive the last number + 1
* @return a range of long values as specified or the empty range if {@code from >= toExclusive}
*/
static Iterator<Long> range(long from, long toExclusive) {
return rangeBy(from, toExclusive, 1);
}
/**
* Creates an Iterator of long numbers starting from {@code from}, extending to {@code toExclusive - 1},
* with {@code step}.
* <p>
* Examples:
* <pre>
* <code>
* Iterator.rangeBy(1L, 3L, 1L) // = (1L, 2L)
* Iterator.rangeBy(1L, 4L, 2L) // = (1L, 3L)
* Iterator.rangeBy(4L, 1L, -2L) // = (4L, 2L)
* Iterator.rangeBy(4L, 1L, 2L) // = ()
* </code>
* </pre>
*
* @param from the first number
* @param toExclusive the last number + 1 if step > 0, the last number - 1 if step < 0
* @param step the step
* @return a range of long values as specified or the empty range if {@code (from == toExclusive) || (step * (from - toExclusive) > 0)}.
* @throws IllegalArgumentException if {@code step} is zero
*/
static Iterator<Long> rangeBy(long from, long toExclusive, long step) {
final long toInclusive = toExclusive - (step > 0 ? 1 : -1);
return rangeClosedBy(from, toInclusive, step);
}
/**
* Creates an Iterator of characters starting from {@code from}, extending to {@code toInclusive}.
* <p>
* Examples:
* <pre>
* <code>
* Iterator.rangeClosed('a', 'c') // = ('a', 'b', 'c')
* Iterator.rangeClosed('c', 'a') // = ()
* </code>
* </pre>
*
* @param from the first character
* @param toInclusive the last character
* @return a range of characters as specified or the empty range if {@code from > toInclusive}
*/
static Iterator<Character> rangeClosed(char from, char toInclusive) {
return rangeClosedBy(from, toInclusive, 1);
}
/**
* Creates an Iterator of characters starting from {@code from}, extending to {@code toInclusive},
* with {@code step}.
* <p>
* Examples:
* <pre>
* <code>
* Iterator.rangeClosedBy('a', 'c', 1) // = ('a', 'b', 'c')
* Iterator.rangeClosedBy('a', 'd', 2) // = ('a', 'c')
* Iterator.rangeClosedBy('d', 'a', -2) // = ('d', 'b')
* Iterator.rangeClosedBy('d', 'a', 2) // = ()
* </code>
* </pre>
*
* @param from the first character
* @param toInclusive the last character
* @param step the step
* @return a range of characters as specified or the empty range if {@code signum(step) == signum(from - toInclusive)}.
* @throws IllegalArgumentException if {@code step} is zero
*/
static Iterator<Character> rangeClosedBy(char from, char toInclusive, int step) {
return rangeClosedBy((int) from, (int) toInclusive, step).map(i -> (char) i.shortValue());
}
@GwtIncompatible
static Iterator<Double> rangeClosedBy(double from, double toInclusive, double step) {
if (from == toInclusive) {
return of(from);
}
final double toExclusive = (step > 0) ? Math.nextUp(toInclusive) : Math.nextDown(toInclusive);
return rangeBy(from, toExclusive, step);
}
/**
* Creates an Iterator of int numbers starting from {@code from}, extending to {@code toInclusive}.
* <p>
* Examples:
* <pre>
* <code>
* Iterator.rangeClosed(0, 0) // = (0)
* Iterator.rangeClosed(2, 0) // = ()
* Iterator.rangeClosed(-2, 2) // = (-2, -1, 0, 1, 2)
* </code>
* </pre>
*
* @param from the first number
* @param toInclusive the last number
* @return a range of int values as specified or the empty range if {@code from > toInclusive}
*/
static Iterator<Integer> rangeClosed(int from, int toInclusive) {
return rangeClosedBy(from, toInclusive, 1);
}
/**
* Creates an Iterator of int numbers starting from {@code from}, extending to {@code toInclusive},
* with {@code step}.
* <p>
* Examples:
* <pre>
* <code>
* Iterator.rangeClosedBy(1, 3, 1) // = (1, 2, 3)
* Iterator.rangeClosedBy(1, 4, 2) // = (1, 3)
* Iterator.rangeClosedBy(4, 1, -2) // = (4, 2)
* Iterator.rangeClosedBy(4, 1, 2) // = ()
* </code>
* </pre>
*
* @param from the first number
* @param toInclusive the last number
* @param step the step
* @return a range of int values as specified or the empty range if {@code signum(step) == signum(from - toInclusive)}.
* @throws IllegalArgumentException if {@code step} is zero
*/
static Iterator<Integer> rangeClosedBy(int from, int toInclusive, int step) {
if (step == 0) {
throw new IllegalArgumentException("step cannot be 0");
} else if (from == toInclusive) {
return of(from);
} else if (Integer.signum(step) == Integer.signum(from - toInclusive)) {
return empty();
} else {
final int end = toInclusive - step;
if (step > 0) {
return new AbstractIterator<Integer>() {
int i = from - step;
@Override
public boolean hasNext() {
return i <= end;
}
@Override
public Integer getNext() {
return i += step;
}
};
} else {
return new AbstractIterator<Integer>() {
int i = from - step;
@Override
public boolean hasNext() {
return i >= end;
}
@Override
public Integer getNext() {
return i += step;
}
};
}
}
}
/**
* Creates an Iterator of long numbers starting from {@code from}, extending to {@code toInclusive}.
* <p>
* Examples:
* <pre>
* <code>
* Iterator.rangeClosed(0L, 0L) // = (0L)
* Iterator.rangeClosed(2L, 0L) // = ()
* Iterator.rangeClosed(-2L, 2L) // = (-2L, -1L, 0L, 1L, 2L)
* </code>
* </pre>
*
* @param from the first number
* @param toInclusive the last number
* @return a range of long values as specified or the empty range if {@code from > toInclusive}
*/
static Iterator<Long> rangeClosed(long from, long toInclusive) {
return rangeClosedBy(from, toInclusive, 1L);
}
/**
* Creates an Iterator of long numbers starting from {@code from}, extending to {@code toInclusive},
* with {@code step}.
* <p>
* Examples:
* <pre>
* <code>
* Iterator.rangeClosedBy(1L, 3L, 1L) // = (1L, 2L, 3L)
* Iterator.rangeClosedBy(1L, 4L, 2L) // = (1L, 3L)
* Iterator.rangeClosedBy(4L, 1L, -2L) // = (4L, 2L)
* Iterator.rangeClosedBy(4L, 1L, 2L) // = ()
* </code>
* </pre>
*
* @param from the first number
* @param toInclusive the last number
* @param step the step
* @return a range of int values as specified or the empty range if {@code signum(step) == signum(from - toInclusive)}.
* @throws IllegalArgumentException if {@code step} is zero
*/
static Iterator<Long> rangeClosedBy(long from, long toInclusive, long step) {
if (step == 0) {
throw new IllegalArgumentException("step cannot be 0");
} else if (from == toInclusive) {
return of(from);
} else if (Long.signum(step) == Long.signum(from - toInclusive)) {
return empty();
} else {
final long end = toInclusive - step;
if (step > 0) {
return new AbstractIterator<Long>() {
long i = from - step;
@Override
public boolean hasNext() {
return i <= end;
}
@Override
public Long getNext() {
return i += step;
}
};
} else {
return new AbstractIterator<Long>() {
long i = from - step;
@Override
public boolean hasNext() {
return i >= end;
}
@Override
public Long getNext() {
return i += step;
}
};
}
}
}
/**
* Returns an infinite iterator of int values starting from {@code value}.
* <p>
* The {@code Iterator} extends to {@code Integer.MIN_VALUE} when passing {@code Integer.MAX_VALUE}.
*
* @param value a start int value
* @return a new {@code Iterator} of int values starting from {@code from}
*/
static Iterator<Integer> from(int value) {
return new AbstractIterator<Integer>() {
private int next = value;
@Override
public boolean hasNext() {
return true;
}
@Override
public Integer getNext() {
return next++;
}
};
}
/**
* Returns an infinite iterator of int values starting from {@code value} and spaced by {@code step}.
* <p>
* The {@code Iterator} extends to {@code Integer.MIN_VALUE} when passing {@code Integer.MAX_VALUE}.
*
* @param value a start int value
* @param step the step by which to advance on each iteration
* @return a new {@code Iterator} of int values starting from {@code from}
*/
static Iterator<Integer> from(int value, int step) {
return new AbstractIterator<Integer>() {
private int next = value;
@Override
public boolean hasNext() {
return true;
}
@Override
public Integer getNext() {
final int result = next;
next += step;
return result;
}
};
}
/**
* Returns an infinite iterator of long values starting from {@code value}.
* <p>
* The {@code Iterator} extends to {@code Long.MIN_VALUE} when passing {@code Long.MAX_VALUE}.
*
* @param value a start long value
* @return a new {@code Iterator} of long values starting from {@code from}
*/
static Iterator<Long> from(long value) {
return new AbstractIterator<Long>() {
private long next = value;
@Override
public boolean hasNext() {
return true;
}
@Override
public Long getNext() {
return next++;
}
};
}
/**
* Returns an infinite iterator of long values starting from {@code value} and spaced by {@code step}.
* <p>
* The {@code Iterator} extends to {@code Long.MIN_VALUE} when passing {@code Long.MAX_VALUE}.
*
* @param value a start long value
* @param step the step by which to advance on each iteration
* @return a new {@code Iterator} of long values starting from {@code from}
*/
static Iterator<Long> from(long value, long step) {
return new AbstractIterator<Long>() {
private long next = value;
@Override
public boolean hasNext() {
return true;
}
@Override
public Long getNext() {
final long result = next;
next += step;
return result;
}
};
}
/**
* Generates an infinite iterator using a value Supplier.
*
* @param supplier A Supplier of iterator values
* @param <T> value type
* @return A new {@code Iterator}
*/
static <T> Iterator<T> continually(Supplier<? extends T> supplier) {
Objects.requireNonNull(supplier, "supplier is null");
return new AbstractIterator<T>() {
@Override
public boolean hasNext() {
return true;
}
@Override
public T getNext() {
return supplier.get();
}
};
}
/**
* Generates an infinite iterator using a function to calculate the next value
* based on the previous.
*
* @param seed The first value in the iterator
* @param f A function to calculate the next value based on the previous
* @param <T> value type
* @return A new {@code Iterator}
*/
static <T> Iterator<T> iterate(T seed, Function<? super T, ? extends T> f) {
Objects.requireNonNull(f, "f is null");
return new AbstractIterator<T>() {
Function<? super T, ? extends T> nextFunc = s -> {
nextFunc = f;
return seed;
};
T current = null;
@Override
public boolean hasNext() {
return true;
}
@Override
public T getNext() {
current = nextFunc.apply(current);
return current;
}
};
}
/**
* Creates an infinite iterator returning the given element.
*
* @param t An element
* @param <T> Element type
* @return A new Iterator containing infinite {@code t}'s.
*/
static <T> Iterator<T> continually(T t) {
return new AbstractIterator<T>() {
@Override
public boolean hasNext() {
return true;
}
@Override
public T getNext() {
return t;
}
};
}
// -- Additional methods of Iterator
@Override
default <R> Iterator<R> collect(PartialFunction<? super T, ? extends R> partialFunction) {
Objects.requireNonNull(partialFunction, "partialFunction is null");
return filter(partialFunction::isDefinedAt).map(partialFunction::apply);
}
// DEV-NOTE: cannot use arg Iterable, it would be ambiguous
default Iterator<T> concat(java.util.Iterator<? extends T> that) {
Objects.requireNonNull(that, "that is null");
if (!that.hasNext()) {
return this;
} else if (!hasNext()) {
return ofAll(that);
} else {
return concat(this, ofAll(that));
}
}
/**
* Inserts an element between all elements of this Iterator.
*
* @param element An element.
* @return an interspersed version of this
*/
default Iterator<T> intersperse(T element) {
if (!hasNext()) {
return empty();
} else {
final Iterator<T> that = this;
return new AbstractIterator<T>() {
boolean insertElement = false;
@Override
public boolean hasNext() {
return that.hasNext();
}
@Override
public T getNext() {
if (insertElement) {
insertElement = false;
return element;
} else {
insertElement = true;
return that.next();
}
}
};
}
}
/**
* Transforms this {@code Iterator}.
*
* @param f A transformation
* @param <U> Type of transformation result
* @return An instance of type {@code U}
* @throws NullPointerException if {@code f} is null
*/
default <U> U transform(Function<? super Iterator<T>, ? extends U> f) {
Objects.requireNonNull(f, "f is null");
return f.apply(this);
}
@Override
default <U> Iterator<Tuple2<T, U>> zip(Iterable<? extends U> that) {
return zipWith(that, Tuple::of);
}
@Override
default <U, R> Iterator<R> zipWith(Iterable<? extends U> that, BiFunction<? super T, ? super U, ? extends R> mapper) {
Objects.requireNonNull(that, "that is null");
Objects.requireNonNull(mapper, "mapper is null");
if (isEmpty()) {
return empty();
} else {
final Iterator<T> it1 = this;
final java.util.Iterator<? extends U> it2 = that.iterator();
return new AbstractIterator<R>() {
@Override
public boolean hasNext() {
return it1.hasNext() && it2.hasNext();
}
@Override
public R getNext() {
return mapper.apply(it1.next(), it2.next());
}
};
}
}
@Override
default <U> Iterator<Tuple2<T, U>> zipAll(Iterable<? extends U> that, T thisElem, U thatElem) {
Objects.requireNonNull(that, "that is null");
final java.util.Iterator<? extends U> thatIt = that.iterator();
if (isEmpty() && !thatIt.hasNext()) {
return empty();
} else {
final Iterator<T> thisIt = this;
return new AbstractIterator<Tuple2<T, U>>() {
@Override
public boolean hasNext() {
return thisIt.hasNext() || thatIt.hasNext();
}
@Override
public Tuple2<T, U> getNext() {
final T v1 = thisIt.hasNext() ? thisIt.next() : thisElem;
final U v2 = thatIt.hasNext() ? thatIt.next() : thatElem;
return Tuple.of(v1, v2);
}
};
}
}
@Override
default Iterator<Tuple2<T, Integer>> zipWithIndex() {
return zipWithIndex(Tuple::of);
}
@Override
default <U> Iterator<U> zipWithIndex(BiFunction<? super T, ? super Integer, ? extends U> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
if (isEmpty()) {
return empty();
} else {
final Iterator<T> it1 = this;
return new AbstractIterator<U>() {
private int index = 0;
@Override
public boolean hasNext() {
return it1.hasNext();
}
@Override
public U getNext() {
return mapper.apply(it1.next(), index++);
}
};
}
}
@Override
default <T1, T2> Tuple2<Iterator<T1>, Iterator<T2>> unzip(
Function<? super T, Tuple2<? extends T1, ? extends T2>> unzipper) {
Objects.requireNonNull(unzipper, "unzipper is null");
if (!hasNext()) {
return Tuple.of(empty(), empty());
} else {
final Stream<Tuple2<? extends T1, ? extends T2>> source = Stream.ofAll(this.map(unzipper));
return Tuple.of(source.map(t -> (T1) t._1).iterator(), source.map(t -> (T2) t._2).iterator());
}
}
@Override
default <T1, T2, T3> Tuple3<Iterator<T1>, Iterator<T2>, Iterator<T3>> unzip3(
Function<? super T, Tuple3<? extends T1, ? extends T2, ? extends T3>> unzipper) {
Objects.requireNonNull(unzipper, "unzipper is null");
if (!hasNext()) {
return Tuple.of(empty(), empty(), empty());
} else {
final Stream<Tuple3<? extends T1, ? extends T2, ? extends T3>> source = Stream.ofAll(this.map(unzipper));
return Tuple.of(source.map(t -> (T1) t._1).iterator(), source.map(t -> (T2) t._2).iterator(), source.map(t -> (T3) t._3).iterator());
}
}
/**
* Creates an iterator from a seed value and a function.
* The function takes the seed at first.
* The function should return {@code None} when it's
* done generating elements, otherwise {@code Some} {@code Tuple}
* of the value to add to the resulting iterator and
* the element for the next call.
* <p>
* Example:
* <pre>
* <code>
* Iterator.unfold(10, x -> x == 0
* ? Option.none()
* : Option.of(new Tuple2<>(x-1, x)));
* // List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
* </code>
* </pre>
*
* @param <T> type of seeds and unfolded values
* @param seed the start value for the iteration
* @param f the function to get the next step of the iteration
* @return a list with the values built up by the iteration
* @throws NullPointerException if {@code f} is null
*/
static <T> Iterator<T> unfold(T seed, Function<? super T, Option<Tuple2<? extends T, ? extends T>>> f) {
return unfoldLeft(seed, f);
}
/**
* Creates an iterator from a seed value and a function.
* The function takes the seed at first.
* The function should return {@code None} when it's
* done generating elements, otherwise {@code Some} {@code Tuple}
* of the value to add to the resulting iterator and
* the element for the next call.
* <p>
* Example:
* <pre>
* <code>
* Iterator.unfoldLeft(10, x -> x == 0
* ? Option.none()
* : Option.of(new Tuple2<>(x-1, x)));
* // List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
* </code>
* </pre>
*
* @param <T> type of seeds
* @param <U> type of unfolded values
* @param seed the start value for the iteration
* @param f the function to get the next step of the iteration
* @return a list with the values built up by the iteration
* @throws NullPointerException if {@code f} is null
*/
static <T, U> Iterator<U> unfoldLeft(T seed, Function<? super T, Option<Tuple2<? extends T, ? extends U>>> f) {
Objects.requireNonNull(f, "f is null");
return Stream.<U> ofAll(
unfoldRight(seed, f.andThen(tupleOpt -> tupleOpt.map(t -> Tuple.of(t._2, t._1)))))
.reverse().iterator();
}
/**
* Creates an iterator from a seed value and a function.
* The function takes the seed at first.
* The function should return {@code None} when it's
* done generating elements, otherwise {@code Some} {@code Tuple}
* of the element for the next call and the value to add to the
* resulting iterator.
* <p>
* Example:
* <pre>
* <code>
* Iterator.unfoldRight(10, x -> x == 0
* ? Option.none()
* : Option.of(new Tuple2<>(x, x-1)));
* // List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
* </code>
* </pre>
*
* @param <T> type of seeds
* @param <U> type of unfolded values
* @param seed the start value for the iteration
* @param f the function to get the next step of the iteration
* @return a list with the values built up by the iteration
* @throws NullPointerException if {@code f} is null
*/
static <T, U> Iterator<U> unfoldRight(T seed, Function<? super T, Option<Tuple2<? extends U, ? extends T>>> f) {
Objects.requireNonNull(f, "the unfold iterating function is null");
return new AbstractIterator<U>() {
private Option<Tuple2<? extends U, ? extends T>> nextVal = f.apply(seed);
@Override
public boolean hasNext() {
return nextVal.isDefined();
}
@Override
public U getNext() {
final U result = nextVal.get()._1;
nextVal = f.apply(nextVal.get()._2);
return result;
}
};
}
// -- Overridden methods of Traversable
@Override
default Iterator<T> distinct() {
if (!hasNext()) {
return empty();
} else {
return new DistinctIterator<>(this, io.vavr.collection.HashSet.empty(), Function.identity());
}
}
@Override
default Iterator<T> distinctBy(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator, "comparator is null");
if (!hasNext()) {
return empty();
} else {
return new DistinctIterator<>(this, TreeSet.empty(comparator), Function.identity());
}
}
@Override
default <U> Iterator<T> distinctBy(Function<? super T, ? extends U> keyExtractor) {
Objects.requireNonNull(keyExtractor, "keyExtractor is null");
if (!hasNext()) {
return empty();
} else {
return new DistinctIterator<>(this, io.vavr.collection.HashSet.empty(), keyExtractor);
}
}
/**
* Removes up to n elements from this iterator.
*
* @param n A number
* @return The empty iterator, if {@code n <= 0} or this is empty, otherwise a new iterator without the first n elements.
*/
@Override
default Iterator<T> drop(int n) {
if (n <= 0) {
return this;
} else if (!hasNext()) {
return empty();
} else {
final Iterator<T> that = this;
return new AbstractIterator<T>() {
long count = n;
@Override
public boolean hasNext() {
while (count > 0 && that.hasNext()) {
that.next(); // discarded
count--;
}
return that.hasNext();
}
@Override
public T getNext() {
return that.next();
}
};
}
}
@Override
default Iterator<T> dropRight(int n) {
if (n <= 0) {
return this;
} else if (!hasNext()) {
return empty();
} else {
final Iterator<T> that = this;
return new AbstractIterator<T>() {
private io.vavr.collection.Queue<T> queue = io.vavr.collection.Queue.empty();
@Override
public boolean hasNext() {
while (queue.length() < n && that.hasNext()) {
queue = queue.append(that.next());
}
return queue.length() == n && that.hasNext();
}
@Override
public T getNext() {
final Tuple2<T, io.vavr.collection.Queue<T>> t = queue.append(that.next()).dequeue();
queue = t._2;
return t._1;
}
};
}
}
@Override
default Iterator<T> dropUntil(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return dropWhile(predicate.negate());
}
@Override
default Iterator<T> dropWhile(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
if (!hasNext()) {
return empty();
} else {
final Iterator<T> that = this;
return new AbstractIterator<T>() {
private T next;
private boolean cached = false;
private boolean first = true;
@Override
public boolean hasNext() {
if (cached) {
return true;
} else if (first) {
first = false;
while (that.hasNext()) {
next = that.next();
if (!predicate.test(next)) {
cached = true;
return true;
}
}
return false;
} else if (that.hasNext()) {
next = that.next();
cached = true;
return true;
} else {
return false;
}
}
@Override
public T getNext() {
cached = false;
return next;
}
};
}
}
/**
* Returns an Iterator that contains elements that satisfy the given {@code predicate}.
*
* @param predicate A predicate
* @return A new Iterator
*/
@Override
default Iterator<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
if (!hasNext()) {
return empty();
} else {
final Iterator<T> that = this;
return new AbstractIterator<T>() {
Option<T> next = Option.none();
@Override
public boolean hasNext() {
while (next.isEmpty() && that.hasNext()) {
final T candidate = that.next();
if (predicate.test(candidate)) {
next = Option.some(candidate);
}
}
return next.isDefined();
}
@Override
public T getNext() {
final T result = next.get();
next = Option.none();
return result;
}
};
}
}
@Override
default Option<T> findLast(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
T last = null;
while (hasNext()) {
final T elem = next();
if (predicate.test(elem)) {
last = elem;
}
}
return Option.of(last);
}
/**
* FlatMaps the elements of this Iterator to Iterables, which are iterated in the order of occurrence.
*
* @param mapper A mapper
* @param <U> Component type
* @return A new Iterable
*/
@Override
default <U> Iterator<U> flatMap(Function<? super T, ? extends Iterable<? extends U>> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
if (!hasNext()) {
return empty();
} else {
final Iterator<T> that = this;
return new AbstractIterator<U>() {
final Iterator<? extends T> inputs = that;
java.util.Iterator<? extends U> current = java.util.Collections.emptyIterator();
@Override
public boolean hasNext() {
boolean currentHasNext;
while (!(currentHasNext = current.hasNext()) && inputs.hasNext()) {
current = mapper.apply(inputs.next()).iterator();
}
return currentHasNext;
}
@Override
public U getNext() {
return current.next();
}
};
}
}
@Override
default <U> U foldRight(U zero, BiFunction<? super T, ? super U, ? extends U> f) {
Objects.requireNonNull(f, "f is null");
return Stream.ofAll(this).foldRight(zero, f);
}
@Override
default T get() {
return head();
}
@Override
default <C> Map<C, Iterator<T>> groupBy(Function<? super T, ? extends C> classifier) {
return io.vavr.collection.Collections.groupBy(this, classifier, Iterator::ofAll);
}
@Override
default Iterator<Seq<T>> grouped(int size) {
return new GroupedIterator<>(this, size, size);
}
@Override
default boolean hasDefiniteSize() {
return false;
}
@Override
default T head() {
if (!hasNext()) {
throw new NoSuchElementException("head() on empty iterator");
}
return next();
}
@Override
default Iterator<T> init() {
if (!hasNext()) {
throw new UnsupportedOperationException();
} else {
return dropRight(1);
}
}
@Override
default Option<Iterator<T>> initOption() {
return hasNext() ? Option.some(init()) : Option.none();
}
/**
* An {@code Iterator} is computed synchronously.
*
* @return false
*/
@Override
default boolean isAsync() {
return false;
}
@Override
default boolean isEmpty() {
return !hasNext();
}
/**
* An {@code Iterator} is computed lazily.
*
* @return true
*/
@Override
default boolean isLazy() {
return true;
}
@Override
default boolean isTraversableAgain() {
return false;
}
@Override
default boolean isSequential() {
return true;
}
@Override
default Iterator<T> iterator() {
return this;
}
@Override
default int length() {
return foldLeft(0, (n, ignored) -> n + 1);
}
/**
* Maps the elements of this Iterator lazily using the given {@code mapper}.
*
* @param mapper A mapper.
* @param <U> Component type
* @return A new Iterator
*/
@Override
default <U> Iterator<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
if (!hasNext()) {
return empty();
} else {
final Iterator<T> that = this;
return new AbstractIterator<U>() {
@Override
public boolean hasNext() {
return that.hasNext();
}
@Override
public U getNext() {
return mapper.apply(that.next());
}
};
}
}
@Override
default Iterator<T> orElse(Iterable<? extends T> other) {
return isEmpty() ? ofAll(other) : this;
}
@Override
default Iterator<T> orElse(Supplier<? extends Iterable<? extends T>> supplier) {
return isEmpty() ? ofAll(supplier.get()) : this;
}
@Override
default Tuple2<Iterator<T>, Iterator<T>> partition(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
if (!hasNext()) {
return Tuple.of(empty(), empty());
} else {
final Stream<T> that = Stream.ofAll(this);
final Iterator<T> first = that.iterator().filter(predicate);
final Iterator<T> second = that.iterator().filter(predicate.negate());
return Tuple.of(first, second);
}
}
@Override
default Iterator<T> peek(Consumer<? super T> action) {
Objects.requireNonNull(action, "action is null");
if (!hasNext()) {
return empty();
} else {
final Iterator<T> that = this;
return new AbstractIterator<T>() {
@Override
public boolean hasNext() {
return that.hasNext();
}
@Override
public T getNext() {
final T next = that.next();
action.accept(next);
return next;
}
};
}
}
@Override
default T reduceLeft(BiFunction<? super T, ? super T, ? extends T> op) {
Objects.requireNonNull(op, "op is null");
if (isEmpty()) {
throw new NoSuchElementException("reduceLeft on Nil");
} else {
final Stream<T> stream = Stream.ofAll(this);
return stream.tail().foldLeft(stream.head(), op);
}
}
@Override
default T reduceRight(BiFunction<? super T, ? super T, ? extends T> op) {
Objects.requireNonNull(op, "op is null");
if (isEmpty()) {
throw new NoSuchElementException("reduceRight on Nil");
} else {
final Stream<T> reversed = Stream.ofAll(this).reverse();
return reversed.reduceLeft((xs, x) -> op.apply(x, xs));
}
}
@Override
default Iterator<T> replace(T currentElement, T newElement) {
if (!hasNext()) {
return empty();
} else {
final Iterator<T> that = this;
return new AbstractIterator<T>() {
boolean isFirst = true;
@Override
public boolean hasNext() {
return that.hasNext();
}
@Override
public T getNext() {
final T elem = that.next();
if (isFirst && Objects.equals(currentElement, elem)) {
isFirst = false;
return newElement;
} else {
return elem;
}
}
};
}
}
@Override
default Iterator<T> replaceAll(T currentElement, T newElement) {
if (!hasNext()) {
return empty();
} else {
final Iterator<T> that = this;
return new AbstractIterator<T>() {
@Override
public boolean hasNext() {
return that.hasNext();
}
@Override
public T getNext() {
final T elem = that.next();
if (Objects.equals(currentElement, elem)) {
return newElement;
} else {
return elem;
}
}
};
}
}
@Override
default Iterator<T> retainAll(Iterable<? extends T> elements) {
return io.vavr.collection.Collections.retainAll(this, elements);
}
@Override
default Traversable<T> scan(T zero, BiFunction<? super T, ? super T, ? extends T> operation) {
return scanLeft(zero, operation);
}
@Override
default <U> Iterator<U> scanLeft(U zero, BiFunction<? super U, ? super T, ? extends U> operation) {
Objects.requireNonNull(operation, "operation is null");
if (isEmpty()) {
return of(zero);
} else {
final Iterator<T> that = this;
return new AbstractIterator<U>() {
boolean isFirst = true;
U acc = zero;
@Override
public boolean hasNext() {
return isFirst || that.hasNext();
}
@Override
public U getNext() {
if (isFirst) {
isFirst = false;
return acc;
} else {
acc = operation.apply(acc, that.next());
return acc;
}
}
};
}
}
// not lazy!
@Override
default <U> Iterator<U> scanRight(U zero, BiFunction<? super T, ? super U, ? extends U> operation) {
Objects.requireNonNull(operation, "operation is null");
if (isEmpty()) {
return of(zero);
} else {
return io.vavr.collection.Collections.scanRight(this, zero, operation, Function.identity());
}
}
@Override
default Iterator<Seq<T>> slideBy(Function<? super T, ?> classifier) {
Objects.requireNonNull(classifier, "classifier is null");
if (!hasNext()) {
return empty();
} else {
final Stream<T> source = Stream.ofAll(this);
return new AbstractIterator<Seq<T>>() {
private Stream<T> that = source;
private Stream<T> next = null;
@Override
public boolean hasNext() {
while (next == null && !that.isEmpty()) {
final Object key = classifier.apply(that.head());
final Tuple2<Stream<T>, Stream<T>> split = that.splitAt(e -> !key.equals(classifier.apply(e)));
next = split._1;
that = split._2;
}
return next != null;
}
@Override
public Stream<T> getNext() {
final Stream<T> result = next;
next = null;
return result;
}
};
}
}
@Override
default Iterator<Seq<T>> sliding(int size) {
return sliding(size, 1);
}
@Override
default Iterator<Seq<T>> sliding(int size, int step) {
return new GroupedIterator<>(this, size, step);
}
@Override
default Tuple2<Iterator<T>, Iterator<T>> span(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
if (!hasNext()) {
return Tuple.of(empty(), empty());
} else {
final Stream<T> that = Stream.ofAll(this);
return Tuple.of(that.iterator().takeWhile(predicate), that.iterator().dropWhile(predicate));
}
}
@Override
default String stringPrefix() {
return "Iterator";
}
@Override
default Iterator<T> tail() {
if (!hasNext()) {
throw new UnsupportedOperationException();
} else {
next(); // remove first element
return this;
}
}
@Override
default Option<Iterator<T>> tailOption() {
if (hasNext()) {
next();
return Option.some(this);
} else {
return Option.none();
}
}
/**
* Take the first n elements from this iterator.
*
* @param n A number
* @return The empty iterator, if {@code n <= 0} or this is empty, otherwise a new iterator without the first n elements.
*/
@Override
default Iterator<T> take(int n) {
if (n <= 0 || !hasNext()) {
return empty();
} else {
final Iterator<T> that = this;
return new AbstractIterator<T>() {
long count = n;
@Override
public boolean hasNext() {
return count > 0 && that.hasNext();
}
@Override
public T getNext() {
count--;
return that.next();
}
};
}
}
@Override
default Iterator<T> takeRight(int n) {
if (n <= 0) {
return empty();
} else {
final Iterator<T> that = this;
return new AbstractIterator<T>() {
private io.vavr.collection.Queue<T> queue = io.vavr.collection.Queue.empty();
@Override
public boolean hasNext() {
while (that.hasNext()) {
queue = queue.enqueue(that.next());
if (queue.length() > n) {
queue = queue.dequeue()._2;
}
}
return queue.length() > 0;
}
@Override
public T getNext() {
final Tuple2<T, io.vavr.collection.Queue<T>> t = queue.dequeue();
queue = t._2;
return t._1;
}
};
}
}
@Override
default Iterator<T> takeUntil(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return takeWhile(predicate.negate());
}
@Override
default Iterator<T> takeWhile(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
if (!hasNext()) {
return empty();
} else {
final Iterator<T> that = this;
return new AbstractIterator<T>() {
private T next;
private boolean cached = false;
private boolean finished = false;
@Override
public boolean hasNext() {
if (cached) {
return true;
} else if (finished) {
return false;
} else if (that.hasNext()) {
next = that.next();
if (predicate.test(next)) {
cached = true;
return true;
}
}
finished = true;
return false;
}
@Override
public T getNext() {
cached = false;
return next;
}
};
}
}
}
interface IteratorModule {
final class ConcatIterator<T> extends AbstractIterator<T> {
private final Iterator<? extends Iterator<? extends T>> iterators;
private Iterator<? extends T> current = Iterator.empty();
ConcatIterator(Iterator<? extends Iterator<? extends T>> iterators) {
this.iterators = iterators;
}
@Override
public boolean hasNext() {
while (!current.hasNext() && !iterators.isEmpty()) {
current = iterators.next();
}
return current.hasNext();
}
@Override
public T getNext() {
return current.next();
}
}
final class DistinctIterator<T, U> extends AbstractIterator<T> {
private final Iterator<? extends T> that;
private io.vavr.collection.Set<U> known;
private final Function<? super T, ? extends U> keyExtractor;
private T next = null;
DistinctIterator(Iterator<? extends T> that, io.vavr.collection.Set<U> set, Function<? super T, ? extends U> keyExtractor) {
this.that = that;
this.known = set;
this.keyExtractor = keyExtractor;
}
@Override
public boolean hasNext() {
while (next == null && that.hasNext()) {
final T elem = that.next();
final U key = keyExtractor.apply(elem);
if (!known.contains(key)) {
known = known.add(key);
next = elem;
}
}
return next != null;
}
@Override
public T getNext() {
final T result = next;
next = null;
return result;
}
}
final class EmptyIterator implements Iterator<Object> {
static final EmptyIterator INSTANCE = new EmptyIterator();
@Override
public boolean hasNext() { return false; }
@Override
public Object next() { throw new NoSuchElementException(stringPrefix() + ".next()"); }
@Override
public String stringPrefix() {
return "EmptyIterator";
}
@Override
public String toString() {
return stringPrefix() + "()";
}
}
final class GroupedIterator<T> implements Iterator<Seq<T>> {
private final Iterator<T> that;
private final int size;
private final int step;
private final int gap;
private final int preserve;
private Object[] buffer;
GroupedIterator(Iterator<T> that, int size, int step) {
if (size < 1 || step < 1) {
throw new IllegalArgumentException("size (" + size + ") and step (" + step + ") must both be positive");
}
this.that = that;
this.size = size;
this.step = step;
this.gap = Math.max(step - size, 0);
this.preserve = Math.max(size - step, 0);
this.buffer = take(that, new Object[size], 0, size);
}
@Override
public boolean hasNext() {
return buffer.length > 0;
}
@Override
public Seq<T> next() {
if (buffer.length == 0) {
throw new NoSuchElementException();
}
final Object[] result = buffer;
if (that.hasNext()) {
buffer = new Object[size];
if (preserve > 0) {
System.arraycopy(result, step, buffer, 0, preserve);
}
if (gap > 0) {
drop(that, gap);
buffer = take(that, buffer, preserve, size);
} else {
buffer = take(that, buffer, preserve, step);
}
} else {
buffer = new Object[0];
}
return Array.wrap(result);
}
private static void drop(Iterator<?> source, int count) {
for (int i = 0; i < count && source.hasNext(); i++) {
source.next();
}
}
private static Object[] take(Iterator<?> source, Object[] target, int offset, int count) {
int i = offset;
while (i < count + offset && source.hasNext()) {
target[i] = source.next();
i++;
}
if (i < target.length) {
final Object[] result = new Object[i];
System.arraycopy(target, 0, result, 0, i);
return result;
} else {
return target;
}
}
}
final class BigDecimalHelper {
@GwtIncompatible("Math::nextDown is not implemented")
private static final Lazy<BigDecimal> INFINITY_DISTANCE = Lazy.of(() -> {
final BigDecimal two = BigDecimal.valueOf(2);
final BigDecimal supremum = BigDecimal.valueOf(Math.nextDown(Double.POSITIVE_INFINITY));
BigDecimal lowerBound = supremum;
BigDecimal upperBound = two.pow(Double.MAX_EXPONENT + 1);
while (true) {
final BigDecimal magicValue = lowerBound.add(upperBound).divide(two, HALF_UP);
if (Double.isInfinite(magicValue.doubleValue())) {
if (areEqual(magicValue, upperBound)) {
return magicValue.subtract(supremum);
}
upperBound = magicValue;
} else {
lowerBound = magicValue;
}
}
});
/* scale-independent equality */
static boolean areEqual(BigDecimal from, BigDecimal toExclusive) {
return from.compareTo(toExclusive) == 0;
}
/* parse infinite values also */
@GwtIncompatible("Math::nextUp is not implemented")
static BigDecimal asDecimal(double number) {
if (number == NEGATIVE_INFINITY) {
final BigDecimal result = BigDecimal.valueOf(Math.nextUp(NEGATIVE_INFINITY));
return result.subtract(INFINITY_DISTANCE.get());
} else if (number == POSITIVE_INFINITY) {
final BigDecimal result = BigDecimal.valueOf(Math.nextDown(POSITIVE_INFINITY));
return result.add(INFINITY_DISTANCE.get());
} else {
return BigDecimal.valueOf(number);
}
}
}
}