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

spark.debug.Iterables Maven / Gradle / Ivy

package spark.debug;

import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import com.google.common.base.Optional;

/**
 * Provides utility functions for efficiently wrapping Iterable objects.
 * Note: Some of these are provided in Guava as well.
 */
public class Iterables {
    @FunctionalInterface
    public static interface Filter {
        /**
         * @param item An item.
         * @return True if item should be included in the output, false otherwise.
         */
        public boolean matches(T item);
    }

    @FunctionalInterface
    public static interface Mapper {
        /**
         * @param item An item.
         * @return The item produced by executing the map function.
         */
        public S map(T item);
    }

    @FunctionalInterface
    public static interface Reducer {
        public S reduce(S accumulator, T item);
    }

    /**
     * @param input  An input iterable.
     * @param filter A filtering function.
     * @return An iterable that provides a view of input which only contains items matching filter.
     */
    public static  Iterable filter(Iterable input, Filter filter) {
        return new Iterable() {
            @Override
            public Iterator iterator() {
                return new FilterIterator(input.iterator(), filter);
            }
        };
    }

    /**
     * Implements a filter iterator.
     *
     * @param  Value type.
     */
    private static final class FilterIterator implements Iterator {
        private final Iterator input;
        private final Filter filter;
        private boolean hasNext = false;
        private T next = null;

        public FilterIterator(Iterator input, Filter filter) {
            this.input = input;
            this.filter = filter;
            advance();
        }

        private void advance() {
            while (input.hasNext()) {
                hasNext = true;
                next = input.next();

                if (filter.matches(next)) {
                    return;
                } else {
                    next = null;
                    hasNext = false;
                }
            }

            next = null;
            hasNext = false;
        }

        @Override
        public boolean hasNext() {
            return hasNext;
        }

        @Override
        public T next() {
            T value = next;
            advance();
            return value;
        }
    }

    /**
     * @param input  An input Iterable.
     * @param mapper A map function.
     * @return A view of input which is obtained by executing the map function on all values in input.
     */
    public static  Iterable map(Iterable input, Mapper mapper) {
        return new Iterable() {
            @Override
            public Iterator iterator() {
                return new MapIterator(input.iterator(), mapper);
            }
        };
    }

    /**
     * Implements a map iterator.
     *
     * @param  Original value type.
     * @param  Mapped value type.
     */
    private static final class MapIterator implements Iterator {
        private final Iterator input;
        private final Mapper mapper;

        public MapIterator(Iterator input, Mapper mapper) {
            this.input = input;
            this.mapper = mapper;
        }

        @Override
        public boolean hasNext() {
            return input.hasNext();
        }

        @Override
        public S next() {
            return mapper.map(input.next());
        }
    }

    /**
     * @param input  An input list.
     * @param mapper A map function.
     * @return The input list of type List (modified in-place from List).
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public static  List mapList(List input, Mapper mapper) {
        ListIterator iterator = input.listIterator();

        while (iterator.hasNext()) {
            iterator.set(mapper.map((T) iterator.next()));
        }

        return (List) input;
    }

    /**
     * @param collection   An iterable.
     * @param initialValue An initial value.
     * @param reducer      A reduction function.
     * @return The reduced value.
     */
    public static  S reduce(Iterable collection, S initialValue, Reducer reducer) {
        S value = initialValue;

        for (T item : collection) {
            value = reducer.reduce(value, item);
        }

        return value;
    }

    /**
     * @param collection An iterable.
     * @param filter     A filter.
     * @return The first item matching the filter (if any).
     */
    public static  Optional first(Iterable collection, Filter filter) {
        for (T item : collection) {
            if (filter.matches(item)) {
                return Optional.of(item);
            }
        }

        return Optional.absent();
    }

    /**
     * @param collection An iterable (non-empty).
     * @return The first item in the given iterable.
     */
    public static  T first(Iterable collection) {
        for (T item : collection) {
            return item;
        }

        throw new IllegalArgumentException("Provided iterable was empty.");
    }
}