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

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