夯實Java基礎(十五)——Java中Comparable和Comparator

一、前言

對於Java中的對象,咱們只能使用基本運算符==、!=來判斷一下地址是否相等,不能使用>、<來比較大小。可是在實際的開發中,咱們須要對對象進行排序,也就是比較大小,那麼應該如何實現呢?這就涉及到了Java中的兩個經常使用的接口Comparable<T>和Comparator<T>的實現了。下面經過示例學習這兩個接口的使用。java

二、Comparable接口

Comparable是一個基於排序接口,它是天然排序。該接口中只有一個compareTo(Obj o)方法,用於給一個類的多個實例比較大小,進而完成排序。也就是說某個類實現了Comparable接口,就意味着該類支持排序。經過實現類重寫compareTo(Obj o)方法,從而規定多個實例的天然順序,而後使用Arrays.sort 或Collections.sort 方法對數組對象或List對象進行排序。數組

用String舉一個簡單的例子:ide

1 public class CompareTest {
2     public static void main(String[] args) {
3         String[] str=new String[]{"AA","EE","DD","CC","FF","BB"};
4         Arrays.sort(str);
5         System.out.println(Arrays.toString(str));
6     }
7 }

運行結果爲:學習

能夠發現,在使用Arrays.sort(str)以後就完成了排序,可是咱們並無調用compareTo(Obj o)方法。咱們知道String源碼中實現了Comparable接口而且重寫該接口的方法,在使用Arrays.sort(str)時sort方法內部間接的調用了String的compareTo(Obj o)方法,因此咱們直接就看到了排序的結果。像String、包裝類等實現了Comparable接口,重寫了compareTo方法,都清晰的給出了比較兩個對象的方式,能夠自行去看一下String重寫的compareTo方法的源碼。可是在重寫compareTo(Obj o)方法時都須要遵循這三個規則:this

①、若是比較者(即this當前對象)大於被比較者(即compareTo方法裏面的形參),則返回正整數。spa

②、若是比較者小於被比較者,那麼返回負整數。code

③、若是比較者等於被比較者,那麼返回零。對象

自定義的類是沒法排序的,可是經過實現Comparable接口以後就能夠實現,而後經過Arrays.sort 或Collections.sort 方法排序。咱們來看一個本身定義的類怎麼使用Comparable接口進行排序:blog

 1 public class Person  implements Comparable{
 2     private String name;
 3     private int age;
 4 
 5     public Person(String name, int age) {
 6         this.name = name;
 7         this.age = age;
 8     }
 9 
10     public String getName() {
11         return name;
12     }
13 
14     public void setName(String name) {
15         this.name = name;
16     }
17 
18     public int getAge() {
19         return age;
20     }
21 
22     public void setAge(int age) {
23         this.age = age;
24     }
25 
26     //按名字排序
27     @Override
28     public int compareTo(Object o) {
29         if(o instanceof Person){
30             Person p= (Person) o;
31             //name是String類型,這裏直接調用String的compareTo
32             if (this.name.compareTo(p.name)>0){
33                 return 1;
34             }else if(this.name.compareTo(p.name)<0){
35                 return -1;
36             }else{
37                 return 0;
38             }
39         }else{
40             throw new RuntimeException("傳入數據類型不一致...");
41         }
42     }
43 
44     public static void main(String[] args) {
45         Person[] p=new Person[5];
46         p[0]=new Person("Jack",23);
47         p[1]=new Person("Marry",13);
48         p[2]=new Person("Tom",18);
49         p[3]=new Person("John",33);
50         p[4]=new Person("Thomas",41);
51         System.out.println("排序前------------");
52         for (Person person : p) {
53             System.out.print(person.getName()+":"+person.getAge()+"\n");
54         }
55         System.out.println("排序後------------");
56         Arrays.sort(p);
57         for (Person person : p) {
58             System.out.print(person.getName()+":"+person.getAge()+"\n");
59         }
60     }
61 }

運行結果爲:排序

在Person類中實現了Comparable接口而且重寫compareTo(Obj o)方法,而後咱們按照名字排序,能夠發現它默認的排序方式是升序,若是要降序則能夠在返回值前面加一個負號。

三、Comparator接口

Comparator也是一個排序接口,它和Comparable功能是同樣的,可是它是定製排序。怎麼來理解定製排序呢?若是某個類沒有實現Comparable接口,而該類自己是不支持排序的,那麼咱們就可使用Comparator來進行排序,或者咱們自定義類實現了Comparable接口後,可是自定義類的代碼不能再更改了,這時須要改變comparaTo(Obj o)方法中排序的方式,此時也能夠選擇定製排序Comparator。Comparator接口中有一個compare(T o1, T o2)方法和compareTo(Obj o)相似,定義排序的規則同樣:

o1>o2,返回值爲正整數。

o1<o2,返回值爲負整數。

o1=o2,返回值爲零。

一樣使用String簡單舉例:

 1 public class CompareTest {
 2     public static void main(String[] args) {
 3         String[] str=new String[]{"AA","EE","DD","CC","FF","BB"};
 4         //使用匿名內部類直接建立
 5         Arrays.sort(str, new Comparator<String>() {
 6             @Override
 7             public int compare(String o1, String o2) {
 8                 if (o1.compareTo(o2)>0){
 9                     return 1;
10                 }else if (o1.compareTo(o2)<0){
11                     return -1;
12                 }else{
13                     return 0;
14                 }
15             }
16         });
17         System.out.println(Arrays.toString(str));
18     }
19 }

咱們知道接口是不能被實例化的,這裏是匿名內部類的知識,能夠自行去度娘尋找答案。

自定義類使用Comparator進行排序:

 1 public class Person{
 2     private String name;
 3     private int age;
 4 
 5     public Person(String name, int age) {
 6         this.name = name;
 7         this.age = age;
 8     }
 9 
10     public String getName() {
11         return name;
12     }
13 
14     public void setName(String name) {
15         this.name = name;
16     }
17 
18     public int getAge() {
19         return age;
20     }
21 
22     public void setAge(int age) {
23         this.age = age;
24     }
25 
26     public static void main(String[] args) {
27         Person[] p=new Person[5];
28         p[0]=new Person("Jack",23);
29         p[1]=new Person("Marry",13);
30         p[2]=new Person("Tom",18);
31         p[3]=new Person("John",33);
32         p[4]=new Person("Thomas",41);
33         System.out.println("排序前------------");
34         for (Person person : p) {
35             System.out.print(person.getName()+":"+person.getAge()+"\n");
36         }
37         System.out.println("排序後------------");
38         Arrays.sort(p, new Comparator<Person>() {
39             //按照年齡默認排序,若是年齡相同則按照名字默認排序
40             @Override
41             public int compare(Person o1, Person o2) {
42                 if (o1 instanceof Person && o2 instanceof Person) {
43                     if (o1.age > o2.age) {
44                         return 1;
45                     }else if (o1.age<o2.age){
46                         return -1;
47                     }else   {
48                         return o1.name.compareTo(o2.name);
49                     }
50                 }else{
51                     throw new RuntimeException("傳入數據類型不一致...");
52                 }
53             }
54         });
55         for (Person person : p) {
56             System.out.print(person.getName()+":"+person.getAge()+"\n");
57         }
58     }
59 }

程序運行結果:

這樣就使用Comparator定製排好序了。

四、小結

小結一下Comparable和Comparator的使用和區別:

①、Comparable是java.lang包下的,而Comparator是java.util包下的。

②、Comparable能夠看作是內部比較器,而Comparator是外部比較器。

③、Comparable是天然排序,Comparator是定製排序。

④、若是某個類沒有實現Comparable接口,而該類自己是不支持排序的,那麼咱們就可使用Comparator來進行定製排序。

⑤、或者咱們自定義類實現了Comparable接口後,可是自定義類的代碼不能再更改了,這時須要改變compareTo(Obj o)方法中排序的方式,此時也能夠選擇定製排序Comparator。

這兩種方法各有優劣:某個類實現了Comparable接口後,在任何地方均可以比較大小,可是有時候須要修改其比較的方式,則須要修原有的代碼。而用Comparator的好處就是不須要修改原有代碼, 而是另外實現一個比較器, 當某個自定義的對象須要做比較的時候,把比較器和對象一塊兒傳遞過去就能夠比大小了, 而且在Comparator 裏面用戶能夠本身實現複雜的能夠通用的邏輯,使其能夠匹配一些比較簡單的對象,那樣就能夠節省不少重複勞動了。

相關文章
相關標籤/搜索