@FunctionalInterface
public interface ThrowingComparator<T, X extends Throwable> {
  public int compare(T o1, T o2) throws X;

  default public Comparator<T> fallbackTo(Comparator<T> fallback) {
    return fallbackTo(fallback, null);
  }

  default public Comparator<T> fallbackTo(Comparator<T> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingComparator<T, Nothing> t = fallback::compare;
    return orTry(t, thrown)::compare;
  }

  default public <Y extends Throwable> ThrowingComparator<T, Y> orTry(
      ThrowingComparator<? super T, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingComparator<T, Y> orTry(
      ThrowingComparator<? super T, ? extends Y> f,
      @Nullable Consumer<? super Throwable> thrown) {
    return (o1, o2) -> {
      ThrowingSupplier<Integer, X> s = () -> compare(o1, o2);
      return s.orTry(() -> f.compare(o1, o2), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingComparator<T, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return (o1, o2) -> {
      ThrowingSupplier<Integer, X> s = () -> compare(o1, o2);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingConsumer<T, X extends Throwable> {
  public void accept(T t) throws X;

  default public Consumer<T> fallbackTo(Consumer<? super T> fallback) {
    return fallbackTo(fallback, null);
  }

  default public Consumer<T> fallbackTo(Consumer<? super T> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingConsumer<T, Nothing> t = fallback::accept;
    return orTry(t, thrown)::accept;
  }

  default public <Y extends Throwable> ThrowingConsumer<T, Y>
      orTry(ThrowingConsumer<? super T, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingConsumer<T, Y> orTry(
      ThrowingConsumer<? super T, ? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingRunnable<X> s = () -> accept(t);
      s.orTry(() -> f.accept(t), thrown).run();
    };
  }

  default public <Y extends Throwable> ThrowingConsumer<T, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingRunnable<X> s = () -> accept(t);
      s.rethrow(x, mapper).run();
    };
  }
} @FunctionalInterface
public interface ThrowingFunction<T, R, X extends Throwable> {
  public R apply(T t) throws X;

  default public Function<T, R> fallbackTo(Function<? super T, ? extends R> fallback) {
    return fallbackTo(fallback, null);
  }

  default public Function<T, R> fallbackTo(Function<? super T, ? extends R> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingFunction<T, R, Nothing> t = fallback::apply;
    return orTry(t, thrown)::apply;
  }

  default public <Y extends Throwable> ThrowingFunction<T, R, Y>
      orTry(ThrowingFunction<? super T, ? extends R, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingFunction<T, R, Y> orTry(
      ThrowingFunction<? super T, ? extends R, ? extends Y> f,
      @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<R, X> s = () -> apply(t);
      return s.orTry(() -> f.apply(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingFunction<T, R, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<R, X> s = () -> apply(t);
      return s.rethrow(x, mapper).get();
    };
  }

  default public <RR> ThrowingFunction<T, RR, X>
      andThen(ThrowingFunction<? super R, ? extends RR, ? extends X> after) {
    Objects.requireNonNull(after);
    return t -> after.apply(apply(t));
  }
} @FunctionalInterface
public interface ThrowingPredicate<T, X extends Throwable> {
  public boolean test(T t) throws X;

  default public Predicate<T> fallbackTo(Predicate<? super T> fallback) {
    return fallbackTo(fallback, null);
  }

  default public Predicate<T> fallbackTo(Predicate<? super T> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingPredicate<T, Nothing> t = fallback::test;
    return orTry(t, thrown)::test;
  }

  default public <Y extends Throwable> ThrowingPredicate<T, Y>
      orTry(ThrowingPredicate<? super T, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingPredicate<T, Y> orTry(
      ThrowingPredicate<? super T, ? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<Boolean, X> s = () -> test(t);
      return s.orTry(() -> f.test(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingPredicate<T, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<Boolean, X> s = () -> test(t);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingToDoubleFunction<T, X extends Throwable> {
  public double applyAsDouble(T value) throws X;

  default public ToDoubleFunction<T> fallbackTo(ToDoubleFunction<? super T> fallback) {
    return fallbackTo(fallback, null);
  }

  default public ToDoubleFunction<T> fallbackTo(ToDoubleFunction<? super T> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingToDoubleFunction<T, Nothing> t = fallback::applyAsDouble;
    return orTry(t, thrown)::applyAsDouble;
  }

  default public <Y extends Throwable> ThrowingToDoubleFunction<T, Y>
      orTry(ThrowingToDoubleFunction<? super T, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingToDoubleFunction<T, Y> orTry(
      ThrowingToDoubleFunction<? super T, ? extends Y> f,
      @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<Double, X> s = () -> applyAsDouble(t);
      return s.orTry(() -> f.applyAsDouble(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingToDoubleFunction<T, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<Double, X> s = () -> applyAsDouble(t);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingToIntFunction<T, X extends Throwable> {
  public int applyAsInt(T value) throws X;

  default public ToIntFunction<T> fallbackTo(ToIntFunction<? super T> fallback) {
    return fallbackTo(fallback, null);
  }

  default public ToIntFunction<T> fallbackTo(ToIntFunction<? super T> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingToIntFunction<T, Nothing> t = fallback::applyAsInt;
    return orTry(t, thrown)::applyAsInt;
  }

  default public <Y extends Throwable> ThrowingToIntFunction<T, Y>
      orTry(ThrowingToIntFunction<? super T, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingToIntFunction<T, Y> orTry(
      ThrowingToIntFunction<? super T, ? extends Y> f,
      @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<Integer, X> s = () -> applyAsInt(t);
      return s.orTry(() -> f.applyAsInt(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingToIntFunction<T, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<Integer, X> s = () -> applyAsInt(t);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingToLongFunction<T, X extends Throwable> {
  public long applyAsLong(T value) throws X;

  default public ToLongFunction<T> fallbackTo(ToLongFunction<? super T> fallback) {
    return fallbackTo(fallback, null);
  }

  default public ToLongFunction<T> fallbackTo(ToLongFunction<? super T> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingToLongFunction<T, Nothing> t = fallback::applyAsLong;
    return orTry(t, thrown)::applyAsLong;
  }

  default public <Y extends Throwable> ThrowingToLongFunction<T, Y>
      orTry(ThrowingToLongFunction<? super T, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingToLongFunction<T, Y> orTry(
      ThrowingToLongFunction<? super T, ? extends Y> f,
      @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<Long, X> s = () -> applyAsLong(t);
      return s.orTry(() -> f.applyAsLong(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingToLongFunction<T, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<Long, X> s = () -> applyAsLong(t);
      return s.rethrow(x, mapper).get();
    };
  }
} public interface ThrowingDoubleStream<X extends Throwable>
    extends ThrowingBaseStream<Double, X, ThrowingDoubleStream<X>>,
    ThrowingDoubleStreamIntermediate<X, ThrowingIntStream<X>, ThrowingLongStream<X>, ThrowingDoubleStream<X>>,
    ThrowingDoubleStreamTerminal<X> {
  @Override
  public ThrowingIterator.OfDouble<X> iterator();

  @Override
  public ThrowingBaseSpliterator.OfDouble<X> spliterator();

  @Override
  default public <U> ThrowingStream<U, X> normalMapToObj(DoubleFunction<? extends U> mapper) {
    return mapToObj(mapper::apply);
  }

  @Override
  public <U> ThrowingStream<U, X> mapToObj(ThrowingDoubleFunction<? extends U, ? extends X> mapper);

  @Override
  public ThrowingStream<Double, X> boxed();

  @Override
  public <Y extends Throwable> ThrowingDoubleStream<Y> rethrow(Class<Y> y,
      Function<? super X, ? extends Y> mapper);
} public interface ThrowingIntStream<X extends Throwable>
    extends ThrowingBaseStream<Integer, X, ThrowingIntStream<X>>,
    ThrowingIntStreamIntermediate<X, ThrowingIntStream<X>, ThrowingLongStream<X>, ThrowingDoubleStream<X>>,
    ThrowingIntStreamTerminal<X> {
  @Override
  public ThrowingIterator.OfInt<X> iterator();

  @Override
  public ThrowingBaseSpliterator.OfInt<X> spliterator();

  @Override
  default public <U> ThrowingStream<U, X> normalMapToObj(IntFunction<? extends U> mapper) {
    return mapToObj(mapper::apply);
  }

  @Override
  public <U> ThrowingStream<U, X> mapToObj(ThrowingIntFunction<? extends U, ? extends X> mapper);

  @Override
  public ThrowingStream<Integer, X> boxed();

  @Override
  public <Y extends Throwable> ThrowingIntStream<Y> rethrow(Class<Y> y,
      Function<? super X, ? extends Y> mapper);
} public interface ThrowingLongStream<X extends Throwable>
    extends ThrowingBaseStream<Long, X, ThrowingLongStream<X>>,
    ThrowingLongStreamIntermediate<X, ThrowingIntStream<X>, ThrowingLongStream<X>, ThrowingDoubleStream<X>>,
    ThrowingLongStreamTerminal<X> {
  @Override
  public ThrowingIterator.OfLong<X> iterator();

  @Override
  public ThrowingBaseSpliterator.OfLong<X> spliterator();

  @Override
  default public <U> ThrowingStream<U, X> normalMapToObj(LongFunction<? extends U> mapper) {
    return mapToObj(mapper::apply);
  }

  @Override
  public <U> ThrowingStream<U, X> mapToObj(ThrowingLongFunction<? extends U, ? extends X> mapper);

  @Override
  public ThrowingStream<Long, X> boxed();

  @Override
  public <Y extends Throwable> ThrowingLongStream<Y> rethrow(Class<Y> y,
      Function<? super X, ? extends Y> mapper);
} public interface ThrowingStream<T, X extends Throwable>
    extends ThrowingBaseStream<T, X, ThrowingStream<T, X>>,
    ThrowingStreamIntermediate<T, X, ThrowingStream<T, X>, ThrowingIntStream<X>, ThrowingLongStream<X>, ThrowingDoubleStream<X>>,
    ThrowingStreamTerminal<T, X> {
  @Override
  public ThrowingIterator<T, X> iterator();

  @Override
  public ThrowingBaseSpliterator.ThrowingSpliterator<T, X> spliterator();

  @Override
  default public <R> ThrowingStream<R, X> normalMap(Function<? super T, ? extends R> mapper) {
    return map(mapper::apply);
  }

  @Override
  public <R> ThrowingStream<R, X> map(ThrowingFunction<? super T, ? extends R, ? extends X> mapper);

  @Override
  default public <R> ThrowingStream<R, X> normalFlatMap(
      Function<? super T, ? extends ThrowingStream<? extends R, ? extends X>> mapper) {
    return flatMap(mapper::apply);
  }

  @Override
  public <R> ThrowingStream<R, X> flatMap(
      ThrowingFunction<? super T, ? extends ThrowingStream<? extends R, ? extends X>, ? extends X> mapper);

  @Override
  public <Y extends Throwable> ThrowingStream<T, Y> rethrow(Class<Y> y,
      Function<? super X, ? extends Y> mapper);

  public static <T, X extends Throwable> ThrowingStream<T, X> of(Stream<T> stream, Class<X> x) {
    return ThrowingBridge.of(stream, x);
  }

  public static <X extends Throwable> ThrowingIntStream<X> of(IntStream stream, Class<X> x) {
    return ThrowingBridge.of(stream, x);
  }

  public static <X extends Throwable> ThrowingLongStream<X> of(LongStream stream, Class<X> x) {
    return ThrowingBridge.of(stream, x);
  }

  public static <X extends Throwable> ThrowingDoubleStream<X> of(DoubleStream stream, Class<X> x) {
    return ThrowingBridge.of(stream, x);
  }
}
import java.util.Comparator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import name.falgout.jeffrey.throwing.ThrowingComparator;
import name.falgout.jeffrey.throwing.ThrowingConsumer;
import name.falgout.jeffrey.throwing.ThrowingFunction;
import name.falgout.jeffrey.throwing.ThrowingPredicate;
import name.falgout.jeffrey.throwing.ThrowingToDoubleFunction;
import name.falgout.jeffrey.throwing.ThrowingToIntFunction;
import name.falgout.jeffrey.throwing.ThrowingToLongFunction;
import name.falgout.jeffrey.throwing.stream.ThrowingDoubleStream;
import name.falgout.jeffrey.throwing.stream.ThrowingIntStream;
import name.falgout.jeffrey.throwing.stream.ThrowingLongStream;
import name.falgout.jeffrey.throwing.stream.ThrowingStream;
package name.falgout.jeffrey.throwing.stream.intermediate;



/**
 * Contains all of the intermediate stream operations for a {@link ThrowingStream}.
 *
 * @param <T>
 *          the type of the stream elements
 * @param <X>
 *          the type of exception this stream accepts
 * @param <S>
 *          the stream type to chain with
 * @param <I>
 *          the IntStream type to chain with
 * @param <L>
 *          the LongStream type to chain with
 * @param <D>
 *          the DoubleStreamType to chain with
 */
public interface ThrowingStreamIntermediate<T, X extends Throwable, S extends ThrowingStreamIntermediate<T, X, S, I, L, D>, I extends ThrowingIntStreamIntermediate<X, I, L, D>, L extends ThrowingLongStreamIntermediate<X, I, L, D>, D extends ThrowingDoubleStreamIntermediate<X, I, L, D>> extends
    ThrowingBaseStreamIntermediate<S> {
  default public S normalFilter(Predicate<? super T> predicate) {
    return filter(predicate::test);
  }

  public S filter(ThrowingPredicate<? super T, ? extends X> predicate);

  default public <R> ThrowingStreamIntermediate<R, X, ?, I, L, D> normalMap(
      Function<? super T, ? extends R> mapper) {
    return this.<R> map(mapper::apply);
  }

  public <R> ThrowingStreamIntermediate<R, X, ?, I, L, D> map(
      ThrowingFunction<? super T, ? extends R, ? extends X> mapper);

  default public I normalMapToInt(ToIntFunction<? super T> mapper) {
    return mapToInt(mapper::applyAsInt);
  }

  public I mapToInt(ThrowingToIntFunction<? super T, ? extends X> mapper);

  default public L normalMapToLong(ToLongFunction<? super T> mapper) {
    return mapToLong(mapper::applyAsLong);
  }

  public L mapToLong(ThrowingToLongFunction<? super T, ? extends X> mapper);

  default public D normalMapToDouble(ToDoubleFunction<? super T> mapper) {
    return mapToDouble(mapper::applyAsDouble);
  }

  public D mapToDouble(ThrowingToDoubleFunction<? super T, ? extends X> mapper);

  default public <R> ThrowingStreamIntermediate<R, X, ?, I, L, D> normalFlatMap(
      Function<? super T, ? extends ThrowingStream<? extends R, ? extends X>> mapper) {
    return this.<R> flatMap(mapper::apply);
  }

  public <R> ThrowingStreamIntermediate<R, X, ?, I, L, D> flatMap(
      ThrowingFunction<? super T, ? extends ThrowingStream<? extends R, ? extends X>, ? extends X> mapper);

  default public I normalFlatMapToInt(
      Function<? super T, ? extends ThrowingIntStream<? extends X>> mapper) {
    return flatMapToInt((ThrowingFunction<? super T, ? extends ThrowingIntStream<? extends X>, ? extends X>) mapper::apply);
  }

  public I flatMapToInt(
      ThrowingFunction<? super T, ? extends ThrowingIntStream<? extends X>, ? extends X> mapper);

  default public L normalFlatMapToLong(
      Function<? super T, ? extends ThrowingLongStream<? extends X>> mapper) {
    return flatMapToLong(mapper::apply);
  }

  public L flatMapToLong(
      ThrowingFunction<? super T, ? extends ThrowingLongStream<? extends X>, ? extends X> mapper);

  default public D normalFlatMapToDouble(
      Function<? super T, ? extends ThrowingDoubleStream<? extends X>> mapper) {
    return flatMapToDouble((ThrowingFunction<? super T, ? extends ThrowingDoubleStream<? extends X>, ? extends X>) mapper::apply);
  }

  public D flatMapToDouble(
      ThrowingFunction<? super T, ? extends ThrowingDoubleStream<? extends X>, ? extends X> mapper);

  public S distinct();

  public S sorted();

  default public S normalSorted(Comparator<? super T> comparator) {
    return sorted(comparator::compare);
  }

  public S sorted(ThrowingComparator<? super T, ? extends X> comparator);