Comparable 和 Comparator比較
- 兩者都 是接口
- Comparable
- 繼承了這個接口,實作接口的方法(自定義排序規則),就表示“該類支援排序”
- 相當于“内部比較”
- 如果某個類實作了這個接口,就可以通過 Arrasys.sort() 對該類的數組排序
- 如果這個類裝在容器中(List,Set),就可以用Collections.sort()排序
- Comparato
- 是比較器的意思,器 相當于工具 ,某個類實作這個接口就可以有比較的規則
- 相當于“外部比較”
a.Comparable 接口
例子**
/**
* @author bigguy_hc
* @create 2018-09-03 11:32
*/
public class Person implements Comparable<Person>{ // 實作接口,重寫方法
int age;
int score;
public Person(){}
public Person(int age,int score){
this.age = age;
this.score = score;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", score=" + score +
'}';
}
@Override
// 重寫方法,自定義排序規則,這裡表示按年齡排序,
public int compareTo(com.bigguy.Person o) {
return this.getAge()-o.getAge();
}
}
測試 Arrays.sort()
// 數組排序
public void test2(){
Person []pers ={new Person(,),new Person(,),new Person(,)};
// 内部判斷的依據是實作了 Comparable 接口,排序規則是 Person 重寫compareTo()方法定義的規則
Arrays.sort(pers);
for (Person per : pers) {
System.out.println(per);
}
}
輸出
Person{age=, score=}
Person{age=, score=}
Person{age=, score=}
測試 Collections.sort()
public void test2(){
Person []pers ={new Person(,),new Person(,),new Person(,)};
List<Person> list = Arrays.asList(pers);
Collections.sort(list); // 内部的比較規則是内部原始的 compareTo()方法
for (Person person : list) {
System.out.println(person);
}
}
輸出
Person{age=, score=}
Person{age=, score=}
Person{age=, score=}
b.Comparator接口
如果就按照上面的代碼(person 實作了Comparable 接口并重寫了對應的方法)
此時,需求改變,現在需要通過 score 從大到小排序,不更改 person 原來代碼,就需要自定義比較器類
class PersonScoreComparator implements Comparator<Person>{
public int compare(Person o1, Person o2) {
return o2.getScore()-o1.getScore();
}
}
public void testComparator(){
Person []pers ={new Person(,),new Person(,),new Person(,)};
List<Person> list = Arrays.asList(pers);
// 這裡傳入一個比較器,裡面自定義了排序規則
Collections.sort(list,new PersonScoreComparator());
for (Person person : list) {
System.out.println(person);
}
}
/*輸出:
Person{age=24, score=100}
Person{age=23, score=91}
Person{age=21, score=85}
*/
注意:
至于什麼時候是升序,什麼時候是降序,就是重寫方法時的規則:
public int compare(Person o1, Person o2) {
return o2.getScore()-o1.getScore(); // 用 o2 - o1 的就是 大 -> 小
}
c.總結
Comparator 的靈活性更高,不修改比較累的原代碼,可以自定義類并重寫方法,但是比較麻煩,
Comparable 簡單,靈活性差,如果需要改變,需要更改原代碼
d. Arrays.sort() 和 Collections.sort() 的 jdk 源碼
Arrays.sort()
public static void sort(Object[] a) {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a);
else
ComparableTimSort.sort(a, , a.length, null, , );
}
Collections.sort() 沒有傳入比較器
public static <T extends Comparable<? super T>> void sort(List<T> list) {
list.sort(null); // 傳入 null 表示傳入的比較器為 null
}
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
public static <T> void sort(T[] a, Comparator<? super T> c) {
if (c == null) { // 因為上面傳入 null ,是以走 sort(a)
sort(a);
} else {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, c);
else
TimSort.sort(a, , a.length, c, null, , );
}
}
Collections.sort() 傳入比較器
public static <T> void sort(List<T> list, Comparator<? super T> c) {
list.sort(c);
}
// 這個方法其實是和上面方法時同一個方法,提高了代碼的複用性
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
總結:
Arrays.sort() 和 Collections.sort() 先判斷是否傳入比較器
如果傳入比較器按比較器的規則比較
否則如果實作了Comparable 接口,按照重寫 的compareTo()方法規則比較
否則,如果還比較則報錯(裡面的元素沒有比較性)