
hm.binkley.util.LinkedIterable Maven / Gradle / Ivy
The newest version!
package hm.binkley.util;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Iterator;
import java.util.Spliterator;
import java.util.function.Function;
import java.util.function.Predicate;
import static java.util.Spliterator.IMMUTABLE;
import static java.util.Spliterator.NONNULL;
import static java.util.Spliterator.ORDERED;
import static java.util.Spliterator.SORTED;
import static java.util.Spliterators.spliteratorUnknownSize;
/**
* {@code LinkedIterable} is a read-only iterable facade over a linked series of values defined by a
* head value and traversal and termination functions. The functions should not structurally modify
* any underlying objects: repeated iterations or stream traversal should produce the same values in
* the same order; best if they are pure functions.
*
* @param the value type
*
* @author B. K. Oxley (binkley)
*/
public final class LinkedIterable
implements Iterable {
/** The characteristics for spliterators. */
public static final int SPLITERATOR_CHARACTERISTICS = IMMUTABLE | NONNULL | ORDERED | SORTED;
private final T head;
private final Function traverse;
private final Predicate terminate;
/**
* Creates a new {@code LinkedIterable} for the given parameters. If head terminates
* the iterable is empty.
*
* @param the value type
* @param head the optional head value
* @param terminate the termination function, never missing
* @param traverse the traversal function, never missing
*
* @return the new {@code LinkedIterable}, never missing
*/
@Nonnull
public static Iterable over(@Nullable final T head,
@Nonnull final Predicate terminate, @Nonnull final Function traverse) {
return new LinkedIterable<>(head, terminate, traverse);
}
/**
* Creates a new {@code LinkedIterable} for the given parameters. If head terminates
* the iterable is empty. Supplies an initial head value equivalent to {@code
* traverse.apply(null)}.
*
* @param the value type
* @param terminate the termination function, never missing
* @param traverse the traversal function, never missing
*
* @return the new {@code LinkedIterable}, never missing
*/
@Nonnull
public static Iterable over(@Nonnull final Predicate terminate,
@Nonnull final Function traverse) {
return new LinkedIterable<>(traverse.apply(null), terminate, traverse);
}
private LinkedIterable(final T head, final Predicate terminate,
final Function traverse) {
this.head = head;
this.terminate = terminate;
this.traverse = traverse;
}
@Override
public Iterator iterator() {
return new Iterator() {
private T last = head;
@Override
public boolean hasNext() {
return !terminate.test(last);
}
@Override
public T next() {
final T next = last;
last = traverse.apply(last);
return next;
}
};
}
@Override
public Spliterator spliterator() {
return spliteratorUnknownSize(iterator(), SPLITERATOR_CHARACTERISTICS);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy