阅读 639

JDK1.8源码解读之 Comparator

前言

  • 比较功能,对某些对象集合施加总排序。
  • 可以将比较器传递给排序方法(例如{@link Collections#sort(List,Comparator)Collections.sort}
  • 或{@link Arrays#sort(Object [],Comparator)Arrays.sort}),以精确控制排序顺序。
  • 比较器还可以用于控制某些数据结构的顺序(例如{@link SortedSet排序集}或{@link SortedMap排序图}),
  • 或为没有{@的对象的集合提供排序链接可比自然排序}。
  • S中的对于每一个e1和e2,当且仅当c.compare(e1,e2)== 0的布尔值与e1.equals(e2)的布尔值相等时,
  • 比较器c才对元素S施加的排序被称为等于equals。
  • 当使用能够施加与等于sorted set(或sorted map)的等于不一致的排序的比较器时,应谨慎行事。
  • 假设将带有显式比较器c的排序集合(或排序映射)与从集合S提取的元素(或键)一起使用。
  • 如果c对S施加的排序与等式不一致,则sorted set(或sorted map)将表现“奇怪”。
  • 特别是,sorted set(或sorted map)将违反set(或map)的一般契约,后者是用eauals定义的。
  • 例如,有两个元素{@code a}和{@code b}, 使得{@code(a.equals(b)&& c.compare(a,b)!= 0)}
  • 将这2个元素添加到到空的 带有比较器 的 TreeSet。
  • 第二个{@code add}操作将返回true(并且tree set 的大小将增加),
  • 因为从树集的角度来看,{@code a}和{@code b}不相等,即使这不符合{@link Set#add Set.add}方法的规范。
  • 注意:比较器通常也要实现java.io.Serializable,这是一个好主意,
  • 因为它们可以用作可序列化数据结构(如{@link TreeSet},{@link TreeMap})中的排序方法。
  • 为了使数据结构成功序列化,比较器(如果提供)必须实现Serializable。

源码



package java.util;
@FunctionalInterface
public interface Comparator<T> {
    /**
     * 第一个参数大于第二个参数,返回正
     * 第一个参数等于第二个参数,返回0
     * 第一个参数小于第二个参数,返回负
     *
     * 实现者必须确保所有x和y的sgn(compare(x,y))== -sgn(compare(y,x))。
     * (这意味着,当且仅当compare(y,x)引发异常时,compare(x,y)才必须引发异常。)
     *
     * 实现者还必须确保该关系是可传递的:(((compare(x,y)> 0)&&(compare(y,z)> 0))意味着compare(x,z)> 0。
     *
     * 最后,实现者必须确保compare(x,y)== 0意味着所有z的sgn(compare(x,z))== sgn(compare(y,z))。
     *
     * 通常是这种情况,但并非严格要求(compare(x,y)== 0)==(x.equals(y))。
     * 一般而言,任何违反此条件的比较器都应明确指出这一事实。
     * 推荐的语言是“注意:此比较器强加与等号不一致的顺序”。
     */
    int compare(T o1, T o2);

    /**
     * 指示其他某个对象是否“等于”该比较器。此方法必须遵守{@link Object#equals(Object)}的一般约定。
     * 此外,仅当指定对象也是一个比较器并且施加与该比较器相同的顺序时,此方法才能返回true。
     * 因此,comp1.equals(comp2)表示每个对象引用o1和o2的sgn(comp1.compare(o1,o2))== sgn(comp2.compare(o1,o2))。
     *
     * 请注意,始终不覆盖Object.equals(Object)始终是安全的。
     * 但是,在某些情况下,重写此方法可以通过允许程序确定两个不同的比较器施加相同的顺序来提高性能。
     */
    boolean equals(Object obj);

    /**
     * 返回强加此比较器相反顺序的比较器。
     */
    default Comparator<T> reversed() {
        return Collections.reverseOrder(this);
    }

    /**
     * 返回带有另一个比较器的字典顺序比较器。
     * 如果此{@code Comparator}认为两个元素相等,即{@code compare(a,b)== 0},则使用{@code other}确定顺序。
     * 如果指定的比较器也可序列化,则返回的比较器可序列化。
     * 例如,要根据长度对{@code String}的集合进行排序,然后对不区分大小写的自然顺序进行排序,可以使用以下代码来组成比较器,
     */
    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);
        };
    }

    /**
     * 返回按字典顺序排序的比较器,该比较器的功能是提取要与给定的{@code Comparator}进行比较的键。
     */
    default <U> Comparator<T> thenComparing(
            Function<? super T, ? extends U> keyExtractor,
            Comparator<? super U> keyComparator)
    {
        return thenComparing(comparing(keyExtractor, keyComparator));
    }

    /**
     * 返回具有按字典顺序排序的比较器,该函数具有提取{@code Comparable}排序键的功能。
     */
    default <U extends Comparable<? super U>> Comparator<T> thenComparing(
            Function<? super T, ? extends U> keyExtractor)
    {
        return thenComparing(comparing(keyExtractor));
    }

    /**
     * 返回具有按字典顺序排序的比较器,该函数具有提取{@code int}排序键的功能。
     */
    default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor) {
        return thenComparing(comparingInt(keyExtractor));
    }

    /**
     * 返回具有按字典顺序排序的比较器,该函数具有提取{@code long}排序键的功能。
     */
    default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor) {
        return thenComparing(comparingLong(keyExtractor));
    }

    /**
     * 返回具有按字典顺序排序的比较器,该函数具有提取{@code double}排序键的功能。
     */
    default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor) {
        return thenComparing(comparingDouble(keyExtractor));
    }

    /**
     * 返回一个强加自然顺序相反的比较器。
     * 返回的比较器是可序列化的,并且在比较{@code null}时抛出{@link NullPointerException}。
     */
    public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
        return Collections.reverseOrder();
    }

    /**
     * 返回一个比较器,该比较器以自然顺序比较{@link Comparable}对象。
     * 返回的比较器是可序列化的,并且在比较{@code null}时抛出{@link NullPointerException}。
     */
    @SuppressWarnings("unchecked")
    public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
        return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
    }

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

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

    /**
     * 接受一个函数,该函数从类型{@code T}中提取排序键,然后返回一个{@code Comparator},
     * 使用指定的{@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));
    }

    /**
     * 接受一个函数,该函数从类型{@code T}中提取一个{@link java.lang.Comparable Comparable}排序键,
     * 并返回一个按该排序键进行比较的{@code Comparator}。如果指定的函数也可序列化,则返回的比较器可序列化。
     */
    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));
    }

    /**
     * 接受一个函数,该函数从类型{@code T}中提取一个{@code int}排序键,并返回一个与该排序键进行比较的{@code Comparator}。
     * 如果指定的函数也可序列化,则返回的比较器可序列化。
     */
    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));
    }

    /**
     * 接受一个函数,该函数从类型{@code T}中提取一个{@code long}排序键,并返回一个与该排序键进行比较的{@code Comparator <T>}。
     * 如果指定的函数也可序列化,则返回的比较器可序列化。
     */
    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));
    }

    /**
     * 接受一个函数,该函数从类型{@code T}中提取一个{@code double}排序键,并返回一个{@code Comparator},并通过该排序键进行比较。
     * 如果指定的函数也可序列化,则返回的比较器可序列化。 
     */
    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));
    }
}

复制代码
文章分类
阅读
文章标签