package java.util;

import java.io.Serializable;
import java.util.function.Function;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.function.ToDoubleFunction;
import java.util.Comparators;

@FunctionalInterface  //这是一个函数型接口,lambda表达式
public interface Comparator<T> {
    //比较两个对象,返回负整数,0正整数分别表示o1<o2,=,>
    int compare(T o1, T o2);

    boolean equals(Object obj);

    //返回一个比较器,这个比较器比较规则与this相反
    default Comparator<T> reversed(){
        return Collections.reverseOrder(this);
    }

    //***********************************************************************************//
    //返回一个字典顺序比较器,需要this比较相等时,利用other比较器进行比较
    default Comparator<T> thenComparing(Comparator<? super T> other){
        Objects.requireNonNull(other);//会抛空对象异常
        return (Comparator<T> & Serializable) (c1, c2) -> {
            int res = compare(c1, c2);
            return (res != 0) ? res : other.compare(c1, c2);
        };
    }

    //返回一个字典顺序比较器,通过调用this.comparing(函数式接口,比较器)方法实现比较
    default <U> Comparator<T> thenComparing(
            Function<? super T, ? extends U> keyExtractor,
            Comparator<? super U> keyComparator){
        return thenComparing(comparing(keyExtractor, keyComparator));
    }

    //返回一个字典顺序比较器,通过调用this.comparing(函数)方法实现比较
    default <U extends Comparable<? super U>> Comparator<T> thenComparing(
            Function<? super T, ? extends U> keyExtractor){
        return thenComparing(comparing(keyExtractor));
    }

    //返回一个字典顺序比较器,通过调用this.comparing(返回Int的函数)方法实现比较
    default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor){
        return thenComparing(comparingInt(keyExtractor));
    }

    //返回一个字典顺序比较器,通过调用this.comparing(返回Long的函数)方法实现比较
    default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor){
        return thenComparing(comparingLong(keyExtractor));
    }

    //返回一个字典顺序比较器,通过调用this.comparing(返回Double的函数)方法实现比较
    default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor){
        return thenComparing(comparingDouble(keyExtractor));
    }

    //返回一个比较器,这个比较器比较规则与this相反,这是静态方法
    public static <T extends Comparable<? super T>> Comparator<T> reverseOrder(){
        return Collections.reverseOrder();
    }

    //返回按原本顺序比较{@link Comparable}对象的比较器。
    @SuppressWarnings("unchecked")
    public static <T extends Comparable<? super T>> Comparator<T> naturalOrder(){
        return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
    }

    //***********************************************************************************//
    //返回一个对空友好的比较器,该比较器认为{@code null}小于非空。
    // 当两者都是{@code null}时,它们被认为是相等的。
    // 如果两者都不为空,则使用指定的{@code Comparator}确定顺序。
    // 如果指定的比较器是{@code null},则返回的比较器将所有非空值视为相等。
    public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator){
        return new Comparators.NullComparator<>(true, comparator);
    }

    //返回一个对空友好的比较器,该比较器认为{@code null}大于于非空。其他同上
    public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator){
        return new Comparators.NullComparator<>(fal***parator);
    }

    //***********************************************************************************//
    // 接受一个函数,该函数从类型{@code T}中提取排序键,
    // 并返回一个{@code Comparator<T>},
    // 该函数使用指定的{@link Comparator}与该排序键进行比较。返回一个比较器
    public static <T, U> Comparator<T> comparing(
            Function<? super T, ? extends U> keyExtractor,
            Comparator<? super U> keyComparator){
        Objects.requireNonNull(keyExtractor);
        Objects.requireNonNull(keyComparator);
        return (Comparator<T> & Serializable)
                (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
                                                  keyExtractor.apply(c2));
    }

    //同上,该函数通过传入的函数提取值,再通过compare方法进行比较,返回一个继承Comparable接口的比较器
    public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
            Function<? super T, ? extends U> keyExtractor){
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
                (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
    }

    //同上,传入的是一个返回Int型接口函数
    public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor){
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
                (c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
    }

    //同上,传入的是一个返回Long型接口函数
    public static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor){
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
                (c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2));
    }

    //同上,传入的是一个返回Double型接口函数
    public static <T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor){
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
                (c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));
    }
    //***********************************************************************************//
}