Comparable和Comparator原始碼分析與對比
阿新 • • 發佈:2019-01-02
Comparable使用
Comparable只是一個簡單的介面,
public interface Comparable<T> {
public int compareTo(T o);
}
使用如下:
public class Person implements Comparable<Person> {
int age;
String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public int compareTo(Person o) {
return this.age - o.age;
}
@Override
public String toString() {
return "age=" + age + ", name='" + name;
}
public static void main(String[] args) {
List<Person> list = Arrays.asList(new Person[]{new Person(23, "Merry"),
new Person(18, "Jack"),
new Person(25, "Lx")});
Collections.sort(list);
System.out.println(list.toString());
}
}
Comparator原始碼如下
Comparator在Java8中是一個函式式介面,除去原始的jdk7中保留的equals
和compare
方法,還添加了部分針對java8函數語言程式設計新增的default
和static
@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 <U extends Comparable<? super U>> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor)
{
return thenComparing(comparing(keyExtractor));
}
/**
* 根據整形關鍵字抽取起返回二次比較器
*
*/
default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor) {
return thenComparing(comparingInt(keyExtractor));
}
/**
* Returns a lexicographic-order comparator with a function that
* extracts a {@code long} sort key.
*/
default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor) {
return thenComparing(comparingLong(keyExtractor));
}
default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor) {
return thenComparing(comparingDouble(keyExtractor));
}
public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
return Collections.reverseOrder();
}
@SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
}
/**
* 返回非空的比較器
*/
public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(true, comparator);
}
public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(false, comparator);
}
/**
* Accepts a function that extracts a sort key from a type {@code T}, and
* returns a {@code Comparator<T>} that compares by that sort key using
*/
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));
}
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));
}
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));
}
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));
}
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));
}
}
Comparator使用方式如下
對一個學生列表,實現按照年齡順序,成績倒序的排序,實現如下:
public class StudentComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.age - o2.age;
}
}
@Data
public class Student {
String name;
int age;
double score;
public Student(String name, int age, float score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}'+"\n";
}
public static void main(String[] args) {
List<Student> list = Arrays.asList(new Student[]{new Student("lx", 27, 99.5f),
new Student("xs", 26, 89.5f),
new Student("mj", 25, 92.5f),
new Student("lx2", 27, 79.5f),
new Student("xs2", 26, 79.5f),
new Student("mj2", 25, 62.5f)}
);
//二次排序採用傳入Lamda表示式的方式
Collections.sort(list, new StudentComparator().thenComparing((s1,s2)->(int)(s2.score-s2.score)));
System.out.println(list.toString());
}
}
執行結果如下:
[Student{name='mj', age=25, score=92.5}
, Student{name='mj2', age=25, score=62.5}
, Student{name='xs', age=26, score=89.5}
, Student{name='xs2', age=26, score=79.5}
, Student{name='lx', age=27, score=99.5}
, Student{name='lx2', age=27, score=79.5}
]
Comparator與Comparable的比較
相同點
- 都是用於比較兩個物件“順序”的介面
- 都可以使用Collections.sort()方法來對物件集合進行排序
不同點
- Comparable位於java.lang包下,而Comparator則位於java.util包下
- Comparable 是在集合內部定義的方法實現的排序,Comparator 是在集合外部實現的排序
- 使用Comparable介面來實現物件之間的比較時,可以使這個型別(設為A)實現Comparable介面,並可以使用Collections.sort()方法來對A型別的List進行排序,之後可以通過a1.comparaTo(a2)來比較兩個物件;
當使用Comparator介面來實現物件之間的比較時,只需要建立一個實現Comparator介面的比較器(設為AComparator),並將其傳給Collections.sort()方法即可對A型別的List進行排序,之後也可以通過呼叫比較器AComparator.compare(a1, a2)來比較兩個物件。例如上面的二次排序問題;
可以說一個是自己完成比較,一個是外部程式實現比較的差別而已。用Comparator 是策略模式(strategy design pattern),就是不改變物件自身,而用一個策略物件(strategy object)來改變它的行為。