package com.github.scr.j8iterables; import com.github.scr.j8iterables.core.Ends; import com.github.scr.j8iterables.core.PeekIterator; import com.github.scr.j8iterables.core.PreviousListIterator; import com.github.scr.j8iterables.core.ToDoubleIterator; import com.github.scr.j8iterables.core.ToIntIterator; import com.github.scr.j8iterables.core.ToLongIterator; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Iterators; import javax.annotation.Nonnull; import java.util.Iterator; import java.util.ListIterator; import java.util.Optional; import java.util.PrimitiveIterator; import java.util.function.Consumer; import java.util.function.ToDoubleFunction; import java.util.function.ToIntFunction; import java.util.function.ToLongFunction; import java.util.stream.Stream; import java.util.stream.StreamSupport; /** * Utility methods to extend Iterators with Java 8 Stream. * * @author scr */ @SuppressWarnings("WeakerAccess") public class J8Iterators { @VisibleForTesting J8Iterators() { } /** * Create a Stream from an iterator. * * @param iterator The iterator to create a Stream from * @param <T> The type of element * @return A Stream object from given iterator. */ @Nonnull public static <T> Stream<T> toStream(Iterator<T> iterator) { return StreamSupport.stream(((Iterable<T>) () -> iterator).spliterator(), false); } /** * Return the first and last elements or {@link Optional#empty()} if {@code Iterators.isEmpty(iterator)}. * * @param iterator The iterator to get the ends from * @param <T> The type of element in the iterator * @return optional {@link Ends} with the first and last of the iterable */ @Nonnull public static <T> Optional<Ends<T>> ends(Iterator<T> iterator) { if (!iterator.hasNext()) { return Optional.empty(); } T first = iterator.next(); return Optional.of(new Ends<>(first, Iterators.getLast(iterator, first))); } /** * Peek at the iterable without modifying the result. * * @param iterator the original iterator * @param consumer the consumer to peek at each element * @param <T> the type of element in the iterator * @return an iterator which sends every element through consumer before returning to the caller */ @Nonnull public static <T> Iterator<T> peek(Iterator<T> iterator, Consumer<? super T> consumer) { return new PeekIterator<>(iterator, consumer); } /** * Iterate a {@link ListIterator} in reverse order. * * @param listIterator the list iterator * @param <T> the type of elements * @return an iterator that walks the listIterator backwards */ @SuppressWarnings("unchecked") @Nonnull public static <T> PreviousListIterator<T> reverse(ListIterator<? extends T> listIterator) { return new PreviousListIterator<>((ListIterator<T>) listIterator); } @Nonnull public static <T> PrimitiveIterator.OfInt mapToInt( Iterator<T> iterator, ToIntFunction<T> toIntFunction) { return new ToIntIterator<>(iterator, toIntFunction); } @Nonnull public static <T> PrimitiveIterator.OfLong mapToLong( Iterator<T> iterator, ToLongFunction<T> toLongFunction) { return new ToLongIterator<>(iterator, toLongFunction); } @Nonnull public static <T> PrimitiveIterator.OfDouble mapToDouble( Iterator<T> iterator, ToDoubleFunction<T> toDoubleFunction) { return new ToDoubleIterator<>(iterator, toDoubleFunction); } }