Comparable/Comparator分析

源码来自jdk1.8


TreeMap, TreeSet, PriorityQueue等天生有序的数据结构,或是Arrays, Collections方法类的排序函数等中,需要对集合元素进行比较,如果不是String或是基本类型等平台自带的类型,就需要自己实现比较元素的方法。

对于Collections来说:

public static > void sort(List list) {
        list.sort(null);
    }

要么是list中的类型原本就实现了Comparable接口

public static  void sort(List list, Comparator c) {
        list.sort(c);
    }

要么是在调用sort的时候提供了这个类型的比较器(实现Comparator接口)

对于Arrays来说:

与Collections也是一样的,提供一个Comparator或者实现Comparable

public static  void sort(T[] a, Comparator c) {
        if (c == null) {
            sort(a);
        } else {
            if (LegacyMergeSort.userRequested)
                legacyMergeSort(a, c);
            else
                TimSort.sort(a, 0, a.length, c, null, 0, 0);
        }
    }
 /**
     * Sorts the specified array of objects into ascending order, according
     * to the {@linkplain Comparable natural ordering} of its elements.
     * All elements in the array must implement the {@link Comparable}
     * interface.  Furthermore, all elements in the array must be
     * mutually comparable (that is, {@code e1.compareTo(e2)} must
     * not throw a {@code ClassCastException} for any elements {@code e1}
     * and {@code e2} in the array).
     *
     * @param a the array to be sorted
     * @throws ClassCastException if the array contains elements that are not
     *         mutually comparable (for example, strings and integers)
     * @throws IllegalArgumentException (optional) if the natural
     *         ordering of the array elements is found to violate the
     *         {@link Comparable} contract
     */
    public static void sort(Object[] a) {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a);
        else
            ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
    }

对TreeSet,TreeMap,PriorityQueue来说:

如果元素类型没有实现Comparable接口,那么在使用的过程中,如add一个元素就会抛出如下异常:

 Exception in thread "main" java.lang.ClassCastException: Collection.User cannot be cast to java.lang.Comparable
    at java.util.TreeMap.compare(TreeMap.java:1290)
    at java.util.TreeMap.put(TreeMap.java:538)
    at java.util.TreeSet.add(TreeSet.java:255)

同样的,也可以在创建TreeMap等数据类型的时候传入一个元素类型的Comparator
由于需要进行比较,所以这些数据结构不允许null值。

什么是Mutually Comparable

为了A类和B类能够互相比较,必须满足如下要求:

  • 对A类的一个对象调用compareTo时传入一个B类的对象(包括子类对象)必须是允许的,也就是不会抛出ClassCastException
  • 对B类的一个对象调用compareTo时传入一个A类的对象(包括子类对象)必须是允许的,也就是不会抛出ClassCastException
  • 如果a.compareTo(b)返回x,那么b.compareTo(a)必须返回一个相反符号的y,如果x==0,那么y==0

Comparable

public interface Comparable {
    /**
     * Compares this object with the specified object for order.  Returns a
     * negative integer, zero, or a positive integer as this object is less
     * than, equal to, or greater than the specified object.
     */
    public int compareTo(T o);
}

Comparator

Comparator接口中给出了很多方法,但除了最核心的compare以外,都给出了默认的实现,所以在使用Comparator时,也只需要实现compare一个方法就可以了:

public interface Comparator {
    /**
     * Compares its two arguments for order.  Returns a negative integer,
     * zero, or a positive integer as the first argument is less than, equal
     * to, or greater than the second.

* * @param o1 the first object to be compared. * @param o2 the second object to be compared. * @return a negative integer, zero, or a positive integer as the * first argument is less than, equal to, or greater than the * second. * @throws NullPointerException if an argument is null and this * comparator does not permit null arguments * @throws ClassCastException if the arguments' types prevent them from * being compared by this comparator. */ int compare(T o1, T o2); // 省略了其他方法 }

Comparator vs Comparable

java.lang.Comparable 用来确定一个类的对象的自然顺序(natural ordering), 然而你可以根据自己的需要使用java.util.Comparator 来确定任何的对象顺序。
你只能通过Comparable确定一个固定的对象顺序,使用Comparator却可以实现任意多个自定义顺序。

Readmore: http://java67.blogspot.com/2013/08/difference-between-comparator-and-comparable-in-java-interface-sorting.html#ixzz490WANROH

你可能感兴趣的:(Comparable/Comparator分析)