package org.zwobble.couscous.util; import com.google.common.collect.Iterables; import java.util.Iterator; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Stream; import java.util.stream.StreamSupport; import static org.zwobble.couscous.util.ExtraLists.list; public class ExtraIterables { private ExtraIterables() {} public static void forEach(Iterable first, Iterable second, Action2 action) { Iterator firstIterator = first.iterator(); Iterator secondIterator = second.iterator(); while (firstIterator.hasNext()) { action.run(firstIterator.next(), secondIterator.next()); } if (secondIterator.hasNext()) { throw new RuntimeException("Iterables not of same length"); } } public static Iterable map(Iterable iterable1, Iterable iterable2, BiFunction function) { return new Iterable() { @Override public Iterator iterator() { Iterator iterator1 = iterable1.iterator(); Iterator iterator2 = iterable2.iterator(); return map(iterator1, iterator2, function); } }; } private static Iterator map(Iterator iterator1, Iterator iterator2, BiFunction function) { return new Iterator() { @Override public boolean hasNext() { return iterator1.hasNext() && iterator2.hasNext(); } @Override public R next() { return function.apply(iterator1.next(), iterator2.next()); } }; } public static Iterable cast(Class type, Iterable iterable) { return new Iterable() { @Override public Iterator iterator() { return cast(type, iterable.iterator()); } }; } private static Iterator cast(Class type, Iterator iterator) { return new Iterator() { @Override public boolean hasNext() { return iterator.hasNext(); } @Override public T next() { Object next = iterator.next(); if (type.isInstance(next)) { return (T) next; } else { throw new ClassCastException(); } } }; } public static Iterable lazyCons(T head, Iterable tails) { return Iterables.concat(list(head), tails); } public static Iterable lazyMap(Iterable iterable, Function function) { return new Iterable() { @Override public Iterator iterator() { return map(iterable.iterator(), function); } }; } private static Iterator map(Iterator iterator, Function function) { return new Iterator() { @Override public boolean hasNext() { return iterator.hasNext(); } @Override public R next() { return function.apply(iterator.next()); } }; } public static Iterable lazyFlatMap(Iterable iterable, Function> function) { return iterable(() -> stream(iterable).flatMap(element -> stream(function.apply(element)))); } public static Stream stream(Iterable iterable) { return StreamSupport.stream(iterable.spliterator(), false); } public static Iterable iterable(Supplier> stream) { return new Iterable() { @Override public Iterator iterator() { return stream.get().iterator(); } }; } }