package org.zwobble.couscous.util; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import java.util.Iterator; import java.util.List; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; public class ExtraLists { public static List list() { return ImmutableList.of(); } public static List list(T value1) { return ImmutableList.of(value1); } public static List list(T value1, T value2) { return ImmutableList.of(value1, value2); } public static List list(T value1, T value2, T value3) { return ImmutableList.of(value1, value2, value3); } public static List list(T... values) { return ImmutableList.copyOf(values); } public static List cons(T value, Iterable list) { return concat(list(value), list); } public static List append(Iterable iterable, T value) { return Stream.concat(ExtraIterables.stream(iterable), Stream.of(value)).collect(Collectors.toList()); } public static List concat(Iterable first, Iterable second) { return ImmutableList.copyOf(Iterables.concat(first, second)); } public static List concat(Iterable first, Iterable second, Iterable third) { return ImmutableList.copyOf(Iterables.concat(first, second, third)); } @SuppressWarnings("unchecked") public static List ofType(List list, Class clazz) { return (List)list.stream() .filter(clazz::isInstance) .collect(Collectors.toList()); } @SuppressWarnings("unchecked") public static List flatMap( Stream stream, CheckedFunction, E> function) throws E { try { return stream .flatMap(value -> { try { return StreamSupport.stream(function.apply(value).spliterator(), false); } catch (Exception exception) { throw new StashedException(exception); } }) .collect(Collectors.toList()); } catch (StashedException exception) { throw (E)exception.exception; } } public static List eagerFilter(Iterable iterable, Predicate predicate) { return StreamSupport.stream(iterable.spliterator(), false) .filter(predicate) .collect(Collectors.toList()); } public static List eagerMap( Iterable iterable, Function function) { return StreamSupport.stream(iterable.spliterator(), false) .map(function) .collect(Collectors.toList()); } public static List eagerMapWithIndex( Iterable iterable, FunctionWithIndex function) { ImmutableList.Builder builder = ImmutableList.builder(); int index = 0; Iterator iterator = iterable.iterator(); while (iterator.hasNext()) { builder.add(function.apply(iterator.next(), index)); index++; } return builder.build(); } public interface FunctionWithIndex { R apply(T value, int index); } public static List eagerMap( Iterable iterable1, Iterable iterable2, BiFunction function) { Iterator iterator1 = iterable1.iterator(); Iterator iterator2 = iterable2.iterator(); ImmutableList.Builder result = ImmutableList.builder(); while (iterator1.hasNext() && iterator2.hasNext()) { result.add(function.apply(iterator1.next(), iterator2.next())); } if (iterator1.hasNext()) { throw new RuntimeException("iterable1 longer than iterable2"); } if (iterator2.hasNext()) { throw new RuntimeException("iterable2 longer than iterable1"); } return result.build(); } public static List eagerFlatMap( Iterable iterable, Function> function) { return StreamSupport.stream(iterable.spliterator(), false) .flatMap(element -> StreamSupport.stream(function.apply(element).spliterator(), false)) .collect(Collectors.toList()); } @FunctionalInterface public interface CheckedFunction { R apply(T value) throws E; } private static class StashedException extends RuntimeException { private static final long serialVersionUID = 1L; private Exception exception; private StashedException(Exception exception) { this.exception = exception; } } public static List copyOf(Iterable iterable) { return ImmutableList.copyOf(iterable); } public static T getLast(T[] values) { return values[values.length - 1]; } public static T getLast(List values) { return values.get(values.size() - 1); } }