java接口Comparable和Comparator源码分析

目录

Comparable

简介

compareTo

Comparator

简介

compare

equals

reversed

thenComparing


Comparable

简介

java接口Comparable和Comparator源码分析_第1张图片

/**
 *
 * 

这个接口强制每个实现它的类的对象排序。这个排序被称为类的自然排序, * 而且这个类的compareTo方法被称为它的自然排序方法。 * *

实现这个接口的对象的列表和数组能被自动排序,通过Collections.sort和Arrays.sort. * 实现这个接口的对象能够不需要指定一个Comparator,就能被用作SortedMap的key或者SortedSet的元素, * *

对一个类C的自然排序被认为与equals方法一致,当且仅当: * 对于类C的每个对象e1和e2,e1.compareTo(e2) == 0和e1.equals(e2)有相同的结果。 * 注意:null不是任何类的实例,并且e.compareTo(null)应该抛出一个NullPointerException, * 即使e.equals(null)返回false * *

强烈建议(尽管不要求)自然排序与equals方法一致。 * 这是因为没有显示的comparator的sorted set和sorted map在它们与 * 自然排序与equals不一致的元素或者key,一起使用时,会显得很奇怪。 * 尤其是,这样的sorted set和sorted map违反了set和map的通用约定, * 这个约定是根据equals方法定义的。 * (因为map和set约定里面的key和元素根据equals是唯一的, * 但是sorted set和sorted map是根据compareTo方法定位的,而不是equals, * 所以如果不一致,会出现equals相同,但是同时出现的元素或者key) * *

举个例子,如果向一个没有使用显示的comparator的sorted set添加两个元素a,b, * 并且 !a.equals(b) && a.compareTo(b) == 0(即equals不相同,compareTo相同), * 第二次添加会返回false(并且sorted set的大小不变),因为在sorted set的观点来看,a和b相同。 * *

事实上所有实现comparable接口的java核心类的自然排序都和equals方法一致。 * 一个例外是java.math.BigDecimal,它的自然排序认为 * 有着相同的值和不同的精度(例如4.0和4.00)是相同的,而它的equals方法认为两者不同。 * *

对于数学上小于的的,一个给定的类C定义的自然顺序的关系是: * x.compareTo(y)<= 0 * 整个的排序相同的关系是: * x.compareTo(y) == 0 * * @param 这个对象可能被比较的对象的类 * * @author Josh Bloch * @see java.util.Comparator * @since 1.2 */ public interface Comparable

compareTo

它里面只有这个方法

   /**
     * 
     * 

为了排序,将这个对象与指定的对象进行比较。 * 当这个对象小于,等于,大于指定对象时,返回一个小于0,等于0,大于0的int * *

实现必须确保sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) * (就是两者的符号必须相反或者同时=0)(sgn就是符号函数,结果是-1,0,1中的一个,代表着参数对应的符号) * 这隐含着如果y.compareTo(x)抛出一个异常,那么x.compareTo(y)必须抛出一个异常。 * *

实现必须也保证关系是传递的。 * (x.compareTo(y)>0 && y.compareTo(z)>0) 隐含着x.compareTo(z)>0) * *

最后实现必须保证x.compareTo(y)==0隐含着 * 对于所有的z,sgn(x.compareTo(z)) == sgn(y.compareTo(z)) * *

强烈建议,但是不严格要求:(x.compareTo(y)==0) == (x.equals(y))。 * 通常地来说,任何实现comparable接口但是违反了这个条件的类应该清楚地指出这个事实。 * 推荐的语言是:注意:这个有自然排序的类与equals不一致。 * Note: this class has a natural ordering that isinconsistent with equals. * *

在上文的描述中,符号sgn,指出来数学上的正负号函数的作用, * 那就是根据表达式的值是负的,0,正的,返回-1,0,1 * * * @param o 被比较的对象 * @return 当这个对象小于,等于,大于指定对象时,返回一个小于0,等于0,大于0的int * * @throws NullPointerException 如果指定对象为空 * @throws ClassCastException 果指定对象的类防止它与这个对象进行比较 */ public int compareTo(T o);

Comparator

简介

java接口Comparable和Comparator源码分析_第2张图片

/**
 * 
 * 

比较功能,对一些对象的集合进行全排序。comparator能够被传递给一个排序方法 * (例如 Collections.sort或者Arrays.sort)来对排序的顺序进行精密的控制。 * comparator也能被用来控制特定数据结构的顺序(例如sorted sets 或者 sorted maps) * 或者为没有实现Comparable接口的对象的集合进行排序。 * *

一个comparator c 对元素集合 S的排序被称为与equals一致, * 当且仅当对于S中的每个e1和e2,c.compare(e1, e2)==0与e1.equals(e2)有同样的boolean值, * *

当对一个sorted set 或者 sorted map ,使用一个排序与equals不一致的comparator时,应该要小心。 * 假设一个sorted set 或者 sorted map 有着一个显示的comparator c 被与从一个set S中的元素使用。 * 如果c对S的排序与equals不一致,sorted set 或者 sorted map会表现的奇怪。 * 尤其是sorted set 或者 sorted map会违反set或者map关于equals的通用约定 * *

举个例子,假设添加两个元素a和b到一个空的treeset,有一个comparator c, * 并且a.equals(b) && c.compare(a, b) != 0 为true。 * 第二个添加会返回true,并且treeset的大小会增加, * 因为a和b在treeset的观点是不同的,即使这违反了set的add方法。 * *

注意:comparator也实现java.io.Serializable通常是一个好主意, * 因为它们可能被用作可序列化的数据结构(如treeset,treemap)的排序方法。 * 为了数据结构成功序列化,comparator(如果提供),必须实现Serializable * (因为treeset内保存comparator,整个treeset序列化,里面的子对象也要序列化) * *

对于制定的comparator c,S中给出的元素 * 如果x<=y,c.compare(x, y)<= 0. * 如果x=y,c.compare(x, y)== 0 * *

不想comparable,一个comparator可能可选择地允许比较null参数, * 然而需要保持等价关系。 * * * @param 通过这个comparator可能比较的对象的类型 * * @author Josh Bloch * @author Neal Gafter * @see Comparable * @see java.io.Serializable * @since 1.2 */ @FunctionalInterface public interface Comparator

 

compare

注意:方法名与comparable的compareTo不一样,但是也是主要方法

    /**
     * 
     * 

为了排序比较两个参数。当第一个参数小于,等于,大于第二个参数时,返回一个负数,0,正数。 * *

在上文的描述中,符号sgn,指出来数学上的正负号函数的作用, * 那就是根据表达式的值是负的,0,正的,返回-1,0,1 * *

实现者必须保证对于所有的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)). * 一般而言,任何comparator违反了这个条件,应该清楚地说明这个事实。 * 建议的语言是 注意:这个有自然排序的类与equals不一致。 * Note: this class has a natural ordering that isinconsistent with equals. * * * @param o1 第一个被比较的对象 * @param o2 第二个被比较的对象 * @return 当第一个参数小于,等于,大于第二个参数时,返回一个负数,0,正数。 * @throws NullPointerException 如果一个参数为null,并且这个comparator不允许null参数 * @throws ClassCastException 如果参数的类型不允许它们被这个comparator比较 */ int compare(T o1, T o2);

equals

表明其他对象是否与这个comparator相同。

    /**
     * 
     * 

表明其他对象是否与这个comparator相同。这个方法必须遵循object的equals方法的通常约定。 * 额外地,这个方法当且仅当特定对象也是一个comparator并且它提供与这个comparator同样的排序时,返回true。 * 因此comp1.equals(comp2) 隐含着对于每个对象引用o1,o2, * sgn(comp1.compare(o1, o2))==sgn(comp2.compare(o1, o2)) * *

注意:不覆盖Object.equals(Object)永远是安全的。(因为object类已经实现了这个方法,实现者comparator必定是object的子类) * 但是,覆盖这个方法可能在某些情况中,通过允许程序确定两个不同的comparator有相同的排序,来提高性能。 * * @param obj the reference object with which to compare. * @return 仅当特定对象也是一个comparator并且它提供与这个comparator同样的排序时,返回true。 * @see Object#equals(Object) * @see Object#hashCode() */ boolean equals(Object obj);

reversed

    /**
     * 返回一个比较器,它执行与这个比较器相反的顺序。
     *
     * @return a comparator that imposes the reverse ordering of this
     *         comparator.
     * @since 1.8
     */
    default Comparator reversed() {
        return Collections.reverseOrder(this);
    }

thenComparing

返回一个二合一的comparator

    /**
     * 

返回一个比较顺序为这个comparator和另一个comparator的comparator。 * 如果这个comparator任务两个元素相同,即compare(a, b) == 0, * 那么使用other这个comparator来确定顺序。 * *

如果指定的comparator是可序列化的,那么返回的comparator也是可序列化的。 * *

例如,为了排序一个string的集合,先根据string的长度排序,然后根据不区分大小写的字母自然排序, * 这个comparator能够以下面的代码组成 * *

* *

{@code
     *     Comparator cmp = Comparator.comparingInt(String::length)
     *             .thenComparing(String.CASE_INSENSITIVE_ORDER);
     * }
* * @param other 当这个comparator比较两个对象,认为它们相同,使用另一个comparator other来比较它们 * @return a lexicographic-order comparator composed of this and then the * other comparator * @throws NullPointerException if the argument is null. * @since 1.8 */ default Comparator thenComparing(Comparator other) { Objects.requireNonNull(other); return (Comparator & Serializable) (c1, c2) -> { int res = compare(c1, c2); //先用这个comparator比较 return (res != 0) ? res : other.compare(c1, c2); //如果结果为0,则用other比较,返回结果为other的 //如果结果不为0,直接返回这个comparator的结果。 }; }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(源码分析,java)