// Path: src/main/java/org/danekja/java/util/function/serializable/SerializableFunction.java
// @FunctionalInterface
// public interface SerializableFunction<T, R> extends Function<T, R>, Serializable {
// 	/**
// 	 * Returns a composed function that first applies the {@code before}
// 	 * function to its input, and then applies this function to the result.
// 	 * If evaluation of either function throws an exception, it is relayed to
// 	 * the caller of the composed function.
// 	 *
// 	 * @param <V> the type of input to the {@code before} function, and to the
// 	 *           composed function
// 	 * @param before the function to apply before this function is applied
// 	 * @return a composed function that first applies the {@code before}
// 	 * function and then applies this function
// 	 * @throws NullPointerException if before is null
// 	 *
// 	 * @see #andThen(Function)
// 	 */
// 	default <V> SerializableFunction<V, R> compose(SerializableFunction<? super V, ? extends T> before) {
// 		Objects.requireNonNull(before);
// 		return (V v) -> apply(before.apply(v));
// 	}
// 
// 	/**
// 	 * Returns a composed function that first applies this function to
// 	 * its input, and then applies the {@code after} function to the result.
// 	 * If evaluation of either function throws an exception, it is relayed to
// 	 * the caller of the composed function.
// 	 *
// 	 * @param <V> the type of output of the {@code after} function, and of the
// 	 *           composed function
// 	 * @param after the function to apply after this function is applied
// 	 * @return a composed function that first applies this function and then
// 	 * applies the {@code after} function
// 	 * @throws NullPointerException if after is null
// 	 *
// 	 * @see #compose(Function)
// 	 */
// 	default <V> SerializableFunction<T, V> andThen(SerializableFunction<? super R, ? extends V> after) {
// 		Objects.requireNonNull(after);
// 		return (T t) -> after.apply(apply(t));
// 	}
// 
// 	/**
// 	 * Returns a function that always returns its input argument.
// 	 *
// 	 * @param <T> the type of the input and output objects to the function
// 	 * @return a function that always returns its input argument
// 	 */
// 	static <T> SerializableFunction<T, T> identity() {
// 		return t -> t;
// 	}
// }
// 
// Path: src/main/java/org/danekja/java/util/function/serializable/SerializableToDoubleFunction.java
// @FunctionalInterface
// public interface SerializableToDoubleFunction<T> extends ToDoubleFunction<T>, Serializable {
// 
// }
// 
// Path: src/main/java/org/danekja/java/util/function/serializable/SerializableToIntFunction.java
// @FunctionalInterface
// public interface SerializableToIntFunction<T> extends ToIntFunction<T>, Serializable {
// 
// }
// 
// Path: src/main/java/org/danekja/java/util/function/serializable/SerializableToLongFunction.java
// @FunctionalInterface
// public interface SerializableToLongFunction<T> extends ToLongFunction<T>, Serializable {
// 
// }


import java.io.Serializable;
import java.util.Collections;
import java.util.Comparator;
import java.util.Objects;
import org.danekja.java.util.function.serializable.SerializableFunction;
import org.danekja.java.util.function.serializable.SerializableToDoubleFunction;
import org.danekja.java.util.function.serializable.SerializableToIntFunction;
import org.danekja.java.util.function.serializable.SerializableToLongFunction;
            SerializableComparator<? super U> keyComparator)
    {
        Objects.requireNonNull(keyExtractor);
        Objects.requireNonNull(keyComparator);
        return
            (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
                                              keyExtractor.apply(c2));
    }

	/**
	 * Accepts a function that extracts a {@link java.lang.Comparable
	 * Comparable} sort key from a type {@code T}, and returns a {@code
	 * Comparator<T>} that compares by that sort key.
	 *
	 * @apiNote
	 * For example, to obtain a {@code SerializableComparator} that compares
	 * {@code Person} objects by their last name,
	 *
	 * <pre>{@code
	 *     Comparator<Person> byLastName = Comparator.comparing(Person::getLastName);
	 * }</pre>
	 *
	 * @param  <T> the type of element to be compared
	 * @param  <U> the type of the {@code Comparable} sort key
	 * @param  keyExtractor the function used to extract the {@link
	 *         Comparable} sort key
	 * @return a comparator that compares by an extracted key
	 * @throws NullPointerException if the argument is null
	 * @since 1.8
	 */
// Path: src/main/java/org/danekja/java/util/function/serializable/SerializableFunction.java
// @FunctionalInterface
// public interface SerializableFunction<T, R> extends Function<T, R>, Serializable {
// 	/**
// 	 * Returns a composed function that first applies the {@code before}
// 	 * function to its input, and then applies this function to the result.
// 	 * If evaluation of either function throws an exception, it is relayed to
// 	 * the caller of the composed function.
// 	 *
// 	 * @param <V> the type of input to the {@code before} function, and to the
// 	 *           composed function
// 	 * @param before the function to apply before this function is applied
// 	 * @return a composed function that first applies the {@code before}
// 	 * function and then applies this function
// 	 * @throws NullPointerException if before is null
// 	 *
// 	 * @see #andThen(Function)
// 	 */
// 	default <V> SerializableFunction<V, R> compose(SerializableFunction<? super V, ? extends T> before) {
// 		Objects.requireNonNull(before);
// 		return (V v) -> apply(before.apply(v));
// 	}
// 
// 	/**
// 	 * Returns a composed function that first applies this function to
// 	 * its input, and then applies the {@code after} function to the result.
// 	 * If evaluation of either function throws an exception, it is relayed to
// 	 * the caller of the composed function.
// 	 *
// 	 * @param <V> the type of output of the {@code after} function, and of the
// 	 *           composed function
// 	 * @param after the function to apply after this function is applied
// 	 * @return a composed function that first applies this function and then
// 	 * applies the {@code after} function
// 	 * @throws NullPointerException if after is null
// 	 *
// 	 * @see #compose(Function)
// 	 */
// 	default <V> SerializableFunction<T, V> andThen(SerializableFunction<? super R, ? extends V> after) {
// 		Objects.requireNonNull(after);
// 		return (T t) -> after.apply(apply(t));
// 	}
// 
// 	/**
// 	 * Returns a function that always returns its input argument.
// 	 *
// 	 * @param <T> the type of the input and output objects to the function
// 	 * @return a function that always returns its input argument
// 	 */
// 	static <T> SerializableFunction<T, T> identity() {
// 		return t -> t;
// 	}
// }
// 
// Path: src/main/java/org/danekja/java/util/function/serializable/SerializableToDoubleFunction.java
// @FunctionalInterface
// public interface SerializableToDoubleFunction<T> extends ToDoubleFunction<T>, Serializable {
// 
// }
// 
// Path: src/main/java/org/danekja/java/util/function/serializable/SerializableToIntFunction.java
// @FunctionalInterface
// public interface SerializableToIntFunction<T> extends ToIntFunction<T>, Serializable {
// 
// }
// 
// Path: src/main/java/org/danekja/java/util/function/serializable/SerializableToLongFunction.java
// @FunctionalInterface
// public interface SerializableToLongFunction<T> extends ToLongFunction<T>, Serializable {
// 
// }


// Path: src/main/java/org/danekja/java/misc/serializable/SerializableComparator.java
import java.io.Serializable;
import java.util.Collections;
import java.util.Comparator;
import java.util.Objects;
import org.danekja.java.util.function.serializable.SerializableFunction;
import org.danekja.java.util.function.serializable.SerializableToDoubleFunction;
import org.danekja.java.util.function.serializable.SerializableToIntFunction;
import org.danekja.java.util.function.serializable.SerializableToLongFunction;

            SerializableComparator<? super U> keyComparator)
    {
        Objects.requireNonNull(keyExtractor);
        Objects.requireNonNull(keyComparator);
        return
            (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
                                              keyExtractor.apply(c2));
    }

	/**
	 * Accepts a function that extracts a {@link java.lang.Comparable
	 * Comparable} sort key from a type {@code T}, and returns a {@code
	 * Comparator<T>} that compares by that sort key.
	 *
	 * @apiNote
	 * For example, to obtain a {@code SerializableComparator} that compares
	 * {@code Person} objects by their last name,
	 *
	 * <pre>{@code
	 *     Comparator<Person> byLastName = Comparator.comparing(Person::getLastName);
	 * }</pre>
	 *
	 * @param  <T> the type of element to be compared
	 * @param  <U> the type of the {@code Comparable} sort key
	 * @param  keyExtractor the function used to extract the {@link
	 *         Comparable} sort key
	 * @return a comparator that compares by an extracted key
	 * @throws NullPointerException if the argument is null
	 * @since 1.8
	 */
    public static <T, U extends Comparable<? super U>> SerializableComparator<T> comparing(