All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javaslang.collection.Iterator Maven / Gradle / Ivy

There is a newer version: 8.1.2
Show newest version
/*     / \____  _    _  ____   ______  / \ ____  __    _______
 *    /  /    \/ \  / \/    \ /  /\__\/  //    \/  \  //  /\__\   JΛVΛSLΛNG
 *  _/  /  /\  \  \/  /  /\  \\__\\  \  //  /\  \ /\\/ \ /__\ \   Copyright 2014-2016 Javaslang, http://javaslang.io
 * /___/\_/  \_/\____/\_/  \_/\__\/__/\__\_/  \_//  \__/\_____/   Licensed under the Apache License, Version 2.0
 */
package javaslang.collection;

import javaslang.Tuple;
import javaslang.Tuple2;
import javaslang.Tuple3;
import javaslang.collection.IteratorModule.ConcatIterator;
import javaslang.collection.IteratorModule.DistinctIterator;
import javaslang.control.Option;

import java.util.Comparator;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * {@code javaslang.collection.Iterator} is a compositional replacement for {@code java.util.Iterator}
 * whose purpose is to iterate once over a sequence of elements.
 * 

* It is recommended to create instances using {@link AbstractIterator} in favor of {@code Iterator}. *

* Note: 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 List#ofAll(Iterable)}. *

* 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}. *

* 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. * * An Iterator that can be only used once because it is a traversal pointer into a collection, and not a collection * itself. * * @param Component type * @author Daniel Dietrich * @since 2.0.0 */ public interface Iterator extends java.util.Iterator, Traversable { // DEV-NOTE: we prefer returning empty() over this if !hasNext() == true in order to free memory. /** * The empty Iterator. */ Iterator EMPTY = new AbstractIterator() { @Override public boolean hasNext() { return false; } @Override public Object getNext() { return null; } }; /** * Creates an Iterator which traverses along the concatenation of the given iterables. * * @param iterables The iterables * @param Component type. * @return A new {@code javaslang.collection.Iterator} */ @SuppressWarnings("varargs") @SafeVarargs static Iterator concat(Iterable... 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 Component type. * @return A new {@code javaslang.collection.Iterator} */ static Iterator concat(Iterable> 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 Component type * @return The empty Iterator */ @SuppressWarnings("unchecked") static Iterator empty() { return (Iterator) EMPTY; } /** * Narrows a widened {@code Iterator} to {@code Iterator} * by performing a type safe-cast. This is eligible because immutable/read-only * collections are covariant. * * @param iterator An {@code Iterator}. * @param Component type of the {@code Iterator}. * @return the given {@code iterator} instance as narrowed type {@code Iterator}. */ @SuppressWarnings("unchecked") static Iterator narrow(Iterator iterator) { return (Iterator) iterator; } /** * Creates an Iterator which traverses one element. * * @param element An element * @param Component type. * @return A new Iterator */ static Iterator of(T element) { return new AbstractIterator() { 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 Component type * @return A new Iterator */ @SafeVarargs static Iterator of(T... elements) { Objects.requireNonNull(elements, "elements is null"); if (elements.length == 0) { return Iterator.empty(); } else { return new AbstractIterator() { 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.of(iterable.iterator()}. * * @param iterable A {@link Iterable} * @param Component type. * @return A new {@code javaslang.collection.Iterator} */ @SuppressWarnings("unchecked") static Iterator ofAll(Iterable iterable) { Objects.requireNonNull(iterable, "iterable is null"); if (iterable instanceof Iterator) { return (Iterator) iterable; } else { return Iterator.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 Component type. * @return A new {@code javaslang.collection.Iterator} */ @SuppressWarnings("unchecked") static Iterator ofAll(java.util.Iterator iterator) { Objects.requireNonNull(iterator, "iterator is null"); if (iterator instanceof Iterator) { return (Iterator) iterator; } else { return new AbstractIterator() { @Override public boolean hasNext() { return iterator.hasNext(); } @Override public T getNext() { return iterator.next(); } }; } } /** * Creates an Iterator based on the elements of a boolean array. * * @param array a boolean array * @return A new Iterator of Boolean values */ static Iterator ofAll(boolean[] array) { Objects.requireNonNull(array, "array is null"); return new AbstractIterator() { int i = 0; @Override public boolean hasNext() { return i < array.length; } @Override public Boolean getNext() { return array[i++]; } }; } /** * Creates an Iterator based on the elements of a byte array. * * @param array a byte array * @return A new Iterator of Byte values */ static Iterator ofAll(byte[] array) { Objects.requireNonNull(array, "array is null"); return new AbstractIterator() { int i = 0; @Override public boolean hasNext() { return i < array.length; } @Override public Byte getNext() { return array[i++]; } }; } /** * Creates an Iterator based on the elements of a char array. * * @param array a char array * @return A new Iterator of Character values */ static Iterator ofAll(char[] array) { Objects.requireNonNull(array, "array is null"); return new AbstractIterator() { int i = 0; @Override public boolean hasNext() { return i < array.length; } @Override public Character getNext() { return array[i++]; } }; } /** * Creates ann Iterator based on the elements of a double array. * * @param array a double array * @return A new Iterator of Double values */ static Iterator ofAll(double[] array) { Objects.requireNonNull(array, "array is null"); return new AbstractIterator() { int i = 0; @Override public boolean hasNext() { return i < array.length; } @Override public Double getNext() { return array[i++]; } }; } /** * Creates an Iterator based on the elements of a float array. * * @param array a float array * @return A new Iterator of Float values */ static Iterator ofAll(float[] array) { Objects.requireNonNull(array, "array is null"); return new AbstractIterator() { int i = 0; @Override public boolean hasNext() { return i < array.length; } @Override public Float getNext() { return array[i++]; } }; } /** * Creates an Iterator based on the elements of an int array. * * @param array an int array * @return A new Iterator of Integer values */ static Iterator ofAll(int[] array) { Objects.requireNonNull(array, "array is null"); return new AbstractIterator() { int i = 0; @Override public boolean hasNext() { return i < array.length; } @Override public Integer getNext() { return array[i++]; } }; } /** * Creates an Iterator based on the elements of a long array. * * @param array a long array * @return A new Iterator of Long values */ static Iterator ofAll(long[] array) { Objects.requireNonNull(array, "array is null"); return new AbstractIterator() { int i = 0; @Override public boolean hasNext() { return i < array.length; } @Override public Long getNext() { return array[i++]; } }; } /** * Creates an Iterator based on the elements of a short array. * * @param array a short array * @return A new Iterator of Short values */ static Iterator ofAll(short[] array) { Objects.requireNonNull(array, "array is null"); return new AbstractIterator() { int i = 0; @Override public boolean hasNext() { return i < array.length; } @Override public Short getNext() { return array[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 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 Iterator tabulate(int n, Function f) { Objects.requireNonNull(f, "f is null"); return Collections.tabulate(n, f); } /** * Returns an Iterator on a sequence of {@code n} values supplied by a given Supplier {@code s}. * * @param 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 Iterator fill(int n, Supplier s) { Objects.requireNonNull(s, "s is null"); return Collections.fill(n, s); } /** * Creates an Iterator of characters starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * Iterator.range('a', 'c')  // = ('a', 'b')
     * Iterator.range('c', 'a')  // = ()
     * 
     * 
* * @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 range(char from, char toExclusive) { return Iterator.rangeBy(from, toExclusive, 1); } /** * Creates an Iterator of characters starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * 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)  // = ()
     * 
     * 
* * @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 (from == toExclusive) || (step * (from - toExclusive) > 0)}. * @throws IllegalArgumentException if {@code step} is zero */ static Iterator rangeBy(char from, char toExclusive, int step) { return Iterator.rangeBy((int) from, (int) toExclusive, step).map(i -> (char) i.shortValue()); } static Iterator rangeBy(double from, double toExclusive, double step) { if (Double.isNaN(from)) { throw new IllegalArgumentException("from is NaN"); } else if (Double.isNaN(toExclusive)) { throw new IllegalArgumentException("toExclusive is NaN"); } else if (Double.isNaN(step)) { throw new IllegalArgumentException("step is NaN"); } else if (step == 0) { throw new IllegalArgumentException("step cannot be 0"); } else if (step * (from - toExclusive) >= 0) { return Iterator.empty(); } else { return new AbstractIterator() { double prev = Double.NaN; double curr = from; boolean hasNext = true; @Override public boolean hasNext() { return hasNext; } @Override public Double getNext() { final double next = curr; if ((step > 0 && curr + step >= toExclusive) || (step < 0 && curr + step <= toExclusive)) { hasNext = false; } else { prev = curr; curr += step; if (curr == prev) { hasNext = false; } } return next; } }; } } /** * Creates an Iterator of int numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * Iterator.range(0, 0)  // = ()
     * Iterator.range(2, 0)  // = ()
     * Iterator.range(-2, 2) // = (-2, -1, 0, 1)
     * 
     * 
* * @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 range(int from, int toExclusive) { return Iterator.rangeBy(from, toExclusive, 1); } /** * Creates an Iterator of int numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * 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)  // = ()
     * 
     * 
* * @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 rangeBy(int from, int toExclusive, int step) { final int one = step > 0 ? 1 : -1; return Iterator.rangeClosedBy(from, toExclusive - one, step); } /** * Creates an Iterator of long numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * Iterator.range(0L, 0L)  // = ()
     * Iterator.range(2L, 0L)  // = ()
     * Iterator.range(-2L, 2L) // = (-2L, -1L, 0L, 1L)
     * 
     * 
* * @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 range(long from, long toExclusive) { return Iterator.rangeBy(from, toExclusive, 1); } /** * Creates an Iterator of long numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * 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)  // = ()
     * 
     * 
* * @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 rangeBy(long from, long toExclusive, long step) { final int one = step > 0 ? 1 : -1; return Iterator.rangeClosedBy(from, toExclusive - one, step); } /** * Creates an Iterator of characters starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * Iterator.rangeClosed('a', 'c')  // = ('a', 'b', 'c')
     * Iterator.rangeClosed('c', 'a')  // = ()
     * 
     * 
* * @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 rangeClosed(char from, char toInclusive) { return Iterator.rangeClosedBy(from, toInclusive, 1); } /** * Creates an Iterator of characters starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * 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)  // = ()
     * 
     * 
* * @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 step * (from - toInclusive) > 0}. * @throws IllegalArgumentException if {@code step} is zero */ static Iterator rangeClosedBy(char from, char toInclusive, int step) { return Iterator.rangeClosedBy((int) from, (int) toInclusive, step).map(i -> (char) i.shortValue()); } static Iterator rangeClosedBy(double from, double toInclusive, double step) { if (Double.isNaN(from)) { throw new IllegalArgumentException("from is NaN"); } else if (Double.isNaN(toInclusive)) { throw new IllegalArgumentException("toInclusive is NaN"); } else if (Double.isNaN(step)) { throw new IllegalArgumentException("step is NaN"); } else if (step == 0) { throw new IllegalArgumentException("step cannot be 0"); } else if (from == toInclusive) { return Iterator.of(from); } else if (step * (from - toInclusive) > 0) { return Iterator.empty(); } else { return new AbstractIterator() { double prev = Double.NaN; double curr = from; boolean hasNext = true; @Override public boolean hasNext() { return hasNext; } @Override public Double getNext() { final double next = curr; if ((step > 0 && curr + step > toInclusive) || (step < 0 && curr + step < toInclusive)) { hasNext = false; } else { prev = curr; curr += step; if (curr == prev) { hasNext = false; } } return next; } }; } } /** * Creates an Iterator of int numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * Iterator.rangeClosed(0, 0)  // = (0)
     * Iterator.rangeClosed(2, 0)  // = ()
     * Iterator.rangeClosed(-2, 2) // = (-2, -1, 0, 1, 2)
     * 
     * 
* * @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 rangeClosed(int from, int toInclusive) { return Iterator.rangeClosedBy(from, toInclusive, 1); } /** * Creates an Iterator of int numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * 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)  // = ()
     * 
     * 
* * @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 step * (from - toInclusive) > 0}. * @throws IllegalArgumentException if {@code step} is zero */ static Iterator rangeClosedBy(int from, int toInclusive, int step) { if (step == 0) { throw new IllegalArgumentException("step cannot be 0"); } else if (from == toInclusive) { return Iterator.of(from); } else if (Integer.signum(step) * Integer.signum(from - toInclusive) > 0) { return Iterator.empty(); } else { return new AbstractIterator() { int i = from; boolean hasNext = true; @Override public boolean hasNext() { return hasNext; } @Override public Integer getNext() { final int next = i; if ((step > 0 && i > toInclusive - step) || (step < 0 && i < toInclusive - step)) { hasNext = false; } else { i += step; } return next; } }; } } /** * Creates an Iterator of long numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * Iterator.rangeClosed(0L, 0L)  // = (0L)
     * Iterator.rangeClosed(2L, 0L)  // = ()
     * Iterator.rangeClosed(-2L, 2L) // = (-2L, -1L, 0L, 1L, 2L)
     * 
     * 
* * @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 rangeClosed(long from, long toInclusive) { return Iterator.rangeClosedBy(from, toInclusive, 1L); } /** * Creates an Iterator of long numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * 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)  // = ()
     * 
     * 
* * @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 step * (from - toInclusive) > 0}. * @throws IllegalArgumentException if {@code step} is zero */ static Iterator rangeClosedBy(long from, long toInclusive, long step) { if (step == 0L) { throw new IllegalArgumentException("step cannot be 0"); } else if (from == toInclusive) { return Iterator.of(from); } else if (Long.signum(step) * Long.signum(from - toInclusive) > 0L) { return Iterator.empty(); } else { return new AbstractIterator() { long i = from; boolean hasNext = true; @Override public boolean hasNext() { return hasNext; } @Override public Long getNext() { final long next = i; if ((step > 0L && i > toInclusive - step) || (step < 0L && i < toInclusive - step)) { hasNext = false; } else { i += step; } return next; } }; } } /** * Returns an infinite iterator of int values starting from {@code value}. *

* 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 from(int value) { return new AbstractIterator() { 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}. *

* 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 from(int value, int step) { return new AbstractIterator() { private int next = value; @Override public boolean hasNext() { return true; } @Override public Integer getNext() { int result = next; next += step; return result; } }; } /** * Returns an infinite iterator of long values starting from {@code value}. *

* 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 from(long value) { return new AbstractIterator() { 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}. *

* 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 from(long value, long step) { return new AbstractIterator() { private long next = value; @Override public boolean hasNext() { return true; } @Override public Long getNext() { long result = next; next += step; return result; } }; } /** * Generates an infinite iterator using a value Supplier. * * @param supplier A Supplier of iterator values * @param value type * @return A new {@code Iterator} */ static Iterator continually(Supplier supplier) { Objects.requireNonNull(supplier, "supplier is null"); return new AbstractIterator() { @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 value type * @return A new {@code Iterator} */ static Iterator iterate(T seed, Function f) { Objects.requireNonNull(f, "f is null"); return new AbstractIterator() { Function 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 Element type * @return A new Iterator containing infinite {@code t}'s. */ static Iterator continually(T t) { return new AbstractIterator() { @Override public boolean hasNext() { return true; } @Override public T getNext() { return t; } }; } // -- Additional methods of Iterator // DEV-NOTE: cannot use arg Iterable, it would be ambiguous default Iterator concat(java.util.Iterator that) { Objects.requireNonNull(that, "that is null"); if (!that.hasNext()) { return this; } else if (!hasNext()) { return Iterator.ofAll(that); } else { return Iterator.concat(this, Iterator.ofAll(that)); } } /** * Inserts an element between all elements of this Iterator. * * @param element An element. * @return an interspersed version of this */ default Iterator intersperse(T element) { if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { 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 Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ default U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } @Override default Iterator> zip(Iterable that) { Objects.requireNonNull(that, "that is null"); if (isEmpty()) { return empty(); } else { final Iterator it1 = this; final java.util.Iterator it2 = that.iterator(); return new AbstractIterator>() { @Override public boolean hasNext() { return it1.hasNext() && it2.hasNext(); } @Override public Tuple2 getNext() { return Tuple.of(it1.next(), it2.next()); } }; } } @Override default Iterator> zipAll(Iterable that, T thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); final java.util.Iterator thatIt = that.iterator(); if (isEmpty() && !thatIt.hasNext()) { return empty(); } else { final Iterator thisIt = this; return new AbstractIterator>() { @Override public boolean hasNext() { return thisIt.hasNext() || thatIt.hasNext(); } @Override public Tuple2 getNext() { T v1 = thisIt.hasNext() ? thisIt.next() : thisElem; U v2 = thatIt.hasNext() ? thatIt.next() : thatElem; return Tuple.of(v1, v2); } }; } } @Override default Iterator> zipWithIndex() { if (isEmpty()) { return empty(); } else { final Iterator it1 = this; return new AbstractIterator>() { private long index = 0; @Override public boolean hasNext() { return it1.hasNext(); } @Override public Tuple2 getNext() { return Tuple.of(it1.next(), index++); } }; } } @Override default Tuple2, Iterator> unzip( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); if (!hasNext()) { return Tuple.of(empty(), empty()); } else { final Stream> 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 Tuple3, Iterator, Iterator> unzip3( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); if (!hasNext()) { return Tuple.of(empty(), empty(), empty()); } else { final Stream> 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()); } } // -- Overridden methods of Traversable @Override default Iterator distinct() { if (!hasNext()) { return empty(); } else { return new DistinctIterator<>(this, HashSet.empty(), Function.identity()); } } @Override default Iterator distinctBy(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); if (!hasNext()) { return empty(); } else { return new DistinctIterator<>(this, TreeSet.empty(comparator), Function.identity()); } } @Override default Iterator distinctBy(Function keyExtractor) { Objects.requireNonNull(keyExtractor, "keyExtractor is null"); if (!hasNext()) { return empty(); } else { return new DistinctIterator<>(this, 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 drop(long n) { if (n <= 0) { return this; } else if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { 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 dropRight(long n) { if (n <= 0) { return this; } else if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { private Queue queue = 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() { Tuple2> t = queue.append(that.next()).dequeue(); queue = t._2; return t._1; } }; } } @Override default Iterator dropUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropWhile(predicate.negate()); } @Override default Iterator dropWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { private T next = null; @Override public boolean hasNext() { while (next == null && that.hasNext()) { final T value = that.next(); if (!predicate.test(value)) { next = value; } } return next != null; } @Override public T getNext() { final T result = next; next = null; return result; } }; } } /** * Returns an Iterator that contains elements that satisfy the given {@code predicate}. * * @param predicate A predicate * @return A new Iterator */ @Override default Iterator filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { Option 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() { T result = next.get(); next = Option.none(); return result; } }; } } @Override default Option findLast(Predicate 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 Component type * @return A new Iterable */ @Override default Iterator flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { final Iterator inputs = that; java.util.Iterator 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 foldRight(U zero, BiFunction f) { Objects.requireNonNull(f, "f is null"); return Stream.ofAll(this).foldRight(zero, f); } @Override default T get() { return head(); } @Override default Map> groupBy(Function classifier) { return Collections.groupBy(this, classifier, Iterator::ofAll); } @Override default Iterator> grouped(long size) { return sliding(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 Option headOption() { return hasNext() ? Option.some(next()) : Option.none(); } @Override default Iterator init() { if (!hasNext()) { throw new UnsupportedOperationException(); } else { return dropRight(1); } } @Override default Option> initOption() { return hasNext() ? Option.some(init()) : Option.none(); } @Override default boolean isEmpty() { return !hasNext(); } @Override default boolean isTraversableAgain() { return false; } @Override default Iterator 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 Component type * @return A new Iterator */ @Override default Iterator map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { @Override public boolean hasNext() { return that.hasNext(); } @Override public U getNext() { return mapper.apply(that.next()); } }; } } @Override default Tuple2, Iterator> partition(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (!hasNext()) { return Tuple.of(empty(), empty()); } else { final Stream that = Stream.ofAll(this); final Iterator first = that.iterator().filter(predicate); final Iterator second = that.iterator().filter(predicate.negate()); return Tuple.of(first, second); } } @Override default Iterator peek(Consumer action) { Objects.requireNonNull(action, "action is null"); if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { @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 op) { Objects.requireNonNull(op, "op is null"); if (isEmpty()) { throw new NoSuchElementException("reduceLeft on Nil"); } else { Stream stream = Stream.ofAll(this); return stream.tail().foldLeft(stream.head(), op); } } @Override default T reduceRight(BiFunction op) { Objects.requireNonNull(op, "op is null"); if (isEmpty()) { throw new NoSuchElementException("reduceRight on Nil"); } else { Stream reversed = Stream.ofAll(this).reverse(); return reversed.tail().foldLeft(reversed.head(), (xs, x) -> op.apply(x, xs)); } } @Override default Iterator replace(T currentElement, T newElement) { if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { boolean done = false; @Override public boolean hasNext() { return that.hasNext(); } @Override public T getNext() { final T elem = that.next(); if (done || !Objects.equals(currentElement, elem)) { return elem; } else { done = true; return newElement; } } }; } } @Override default Iterator replaceAll(T currentElement, T newElement) { if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { @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; } } }; } } @SuppressWarnings("unchecked") @Override default Iterator retainAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); // DEV-NOTE: Only Eclipse does need this unchecked cast, IntelliJ and javac are fine. return hasNext() ? filter(HashSet.ofAll((Iterable) elements)::contains) : empty(); } @Override default Traversable scan(T zero, BiFunction operation) { return scanLeft(zero, operation); } @Override default Iterator scanLeft(U zero, BiFunction operation) { Objects.requireNonNull(operation, "operation is null"); if (isEmpty()) { return Iterator.of(zero); } else { final Iterator that = this; return new AbstractIterator() { 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 Iterator scanRight(U zero, BiFunction operation) { Objects.requireNonNull(operation, "operation is null"); if (isEmpty()) { return Iterator.of(zero); } else { return Collections.scanRight(this, zero, operation, Stream.empty(), Stream::prepend, Stream::iterator); } } @Override default Iterator> sliding(long size) { return sliding(size, 1); } @Override default Iterator> sliding(long size, long step) { if (size <= 0 || step <= 0) { throw new IllegalArgumentException(String.format("size: %s or step: %s not positive", size, step)); } if (!hasNext()) { return empty(); } else { final Stream source = Stream.ofAll(this); return new AbstractIterator>() { private Stream that = source; private IndexedSeq next = null; @Override public boolean hasNext() { while (next == null && !that.isEmpty()) { final Tuple2, Stream> split = that.splitAt(size); next = split._1.toVector(); that = split._2.isEmpty() ? Stream. empty() : that.drop(step); } return next != null; } @Override public IndexedSeq getNext() { final IndexedSeq result = next; next = null; return result; } }; } } @Override default Tuple2, Iterator> span(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (!hasNext()) { return Tuple.of(empty(), empty()); } else { Stream that = Stream.ofAll(this); return Tuple.of(that.iterator().takeWhile(predicate), that.iterator().dropWhile(predicate)); } } @Override default Spliterator spliterator() { // the focus of the Stream API is on random-access collections of *known size* Stream stream = Stream.ofAll(this); return Spliterators.spliterator(stream.iterator(), stream.length(), Spliterator.ORDERED | Spliterator.IMMUTABLE); } @Override default String stringPrefix() { return "Iterator"; } @Override default Iterator tail() { if (!hasNext()) { throw new UnsupportedOperationException(); } else { next(); // remove first element return this; } } @Override default Option> 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 take(long n) { if (n <= 0 || !hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { long count = n; @Override public boolean hasNext() { return count > 0 && that.hasNext(); } @Override public T getNext() { count--; return that.next(); } }; } } @Override default Iterator takeRight(long n) { if (n <= 0) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { private Queue queue = 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 = queue.dequeue(); queue = t._2; return t._1; } }; } } @Override default Iterator takeUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeWhile(predicate.negate()); } @Override default Iterator takeWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { private T next = null; private boolean finished = false; @Override public boolean hasNext() { while (!finished && next == null && that.hasNext()) { final T value = that.next(); if (predicate.test(value)) { next = value; } else { finished = true; } } return next != null; } @Override public T getNext() { final T result = next; next = null; return result; } }; } } } interface IteratorModule { final class ConcatIterator extends AbstractIterator { private final Iterator> iterators; private Iterator current; ConcatIterator(Iterator> iterators) { this.current = Iterator.empty(); 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 extends AbstractIterator { private final Iterator that; private Set known; private final Function keyExtractor; private T next = null; DistinctIterator(Iterator that, Set set, Function 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; } } }