目录
Comparable
简介
compareTo
Comparator
简介
compare
equals
reversed
thenComparing
/**
*
* 这个接口强制每个实现它的类的对象排序。这个排序被称为类的自然排序,
* 而且这个类的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
它里面只有这个方法
/**
*
* 为了排序,将这个对象与指定的对象进行比较。
* 当这个对象小于,等于,大于指定对象时,返回一个小于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能够被传递给一个排序方法
* (例如 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
注意:方法名与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);
表明其他对象是否与这个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);
/**
* 返回一个比较器,它执行与这个比较器相反的顺序。
*
* @return a comparator that imposes the reverse ordering of this
* comparator.
* @since 1.8
*/
default Comparator reversed() {
return Collections.reverseOrder(this);
}
返回一个二合一的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 super T> 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的结果。
};
}