- Comparable:
实现 Comparable 接口的类的对象可以用作 “有序映射(如TreeMap)” 中的键或 “有序集合(TreeSet)” 中的元素,而不需要指定比较器。
package java.lang;
import java.util.*;
public interface Comparable<T> {
public int compareTo(T o);
}
Comparable 中的 compareTo 方法有一个参数,这个参数就看做传入对象,将传入对象看做other:
this < other :负整数,默认使用-1(降序)
this == other :零,默认使用0 (不变)
this > other :正整数,默认使用 1 (升序)
PS:升序:当前对象 - 传入对象;降序:传入对象 - 当前对象
- Comparator :
Comparator 是比较器接口。
我们若需要控制某个类的次序,而该类本身不支持排序(即没有实现 Comparable 接口);那么,我们可以建立一个 “该类的比较器” 来进行排序。这个 “比较器” 只需要实现 Comparator 接口即可。
也就是说,我们可以通过“实现Comparator类来新建一个比较器”,然后通过该比较器对类进行排序。
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
default Comparator<T> reversed() {
return Collections.reverseOrder(this);
}
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);
};
}
default <U> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
return thenComparing(comparing(keyExtractor, keyComparator));
}
//...(default 和 static 方法)
}
若一个类要实现Comparator接口:它一定要实现compareTo(T o1, T o2) 函数,但可以不实现 equals(Object obj) 函数。为什么可以不实现 equals(Object obj) 函数呢? 因为任何类,默认都是已经实现了equals(Object obj)的。 Java中的一切类都是继承于java.lang.Object,在Object.java中实现了equals(Object obj)函数,所以,其它所有的类也相当于都实现了该函数。
int compare(T o1, T o2) 比较其两个顺序的参数。
第一个参数就是当前对象,即this;第二个参数就是传入对象,即 other
this < other :负整数:默认使用-1(降序)
this == other :零:默认使用0 (不变)
this > other :正整数:默认使用 1 (升序)
PS:升序:当前对象 - 传入对象;降序:传入对象 - 当前对象
- Comparator 和 Comparable:
Comparable 是排序接口,若一个类实现了 Comparable 接口,就意味着 “该类支持排序”。而Comparator是比较器,我们若需要控制某个类的次序,可以建立一个 “该类的比较器” 来进行排序。
Comparable 相当于 “内部比较器”,而 Comparator 相当于 “外部比较器”。
用 Comparable 简单, 只要实现 Comparable 接口的对象直接就成为一个可以比较的对象,但是需要修改源代码。 用Comparator 的好处是不需要修改源代码, 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了。
Comparator 还可以用来做一些通用的逻辑,用以匹配多种比较简单的对象,节省很多重复劳动。