對於Java中的對象,咱們只能使用基本運算符==、!=來判斷一下地址是否相等,不能使用>、<來比較大小。可是在實際的開發中,咱們須要對對象進行排序,也就是比較大小,那麼應該如何實現呢?這就涉及到了Java中的兩個經常使用的接口Comparable<T>和Comparator<T>的實現了。下面經過示例學習這兩個接口的使用。java
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也是一個排序接口,它和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 裏面用戶能夠本身實現複雜的能夠通用的邏輯,使其能夠匹配一些比較簡單的對象,那樣就能夠節省不少重複勞動了。