最近在學習貪心算法和動態規划的過程中,里面有一段自然排序的操作,順便簡單了解一下Java中對象比較后排序要使用的兩個接口:Comparable和Comparator。如果是數字,直接比較就行,但是如果是對象,如何比較后排序呢?就需要用到這兩個接口了,並且將自己定義的類作為參數傳入接口泛型,在接口里重寫比較方法,將自己要選擇排序的類屬性添加到比較條件中去。
接口主要區別
(1)Comparable接口是在java.lang下,Comparator接口是在java.util下。
(2)如果在定義類時,就實現了Comparable接口,直接在里面重寫compareTo()方法,如果沒實現,后面在業務開發中需要有比較排序的功能,就再單獨寫一個類實現Comparator接口,在里面重寫compare()方法,然后這個類需要作為參數傳入到工具類Collections.sort和Arrays.sort方法中。
(3)實現Comparable接口的類必須是自然排序,另外一個不是強制條件。
使用Comparable
(1)定義實現類時,實現Comparable接口。
1 /** 2 * 實體類,實現Comparable接口 3 */ 4 public class Person implements Comparable<Person>{ 5 6 //屬性 7 private String name; 8 private int age; 9 private int salary; 10 11 //get和set方法 12 public String getName() { 13 return name; 14 } 15 16 public void setName(String name) { 17 this.name = name; 18 } 19 20 public int getAge() { 21 return age; 22 } 23 24 public void setAge(int age) { 25 this.age = age; 26 } 27 28 public int getSalary() { 29 return salary; 30 } 31 32 public void setSalary(int salary) { 33 this.salary = salary; 34 } 35 36 //構造方法 37 public Person(String name, int age, int salary) { 38 this.name = name; 39 this.age = age; 40 this.salary = salary; 41 } 42 43 @Override 44 public String toString() { 45 return "Person{" + 46 "name='" + name + '\'' + 47 ", age=" + age + 48 ", salary=" + salary + 49 '}'; 50 } 51 52 //重寫接口方法,o為要比較的對象 53 @Override 54 public int compareTo(Person o) { 55 //大於要比較的對象就返回1 56 if(this.salary>o.getSalary()){ 57 return 1; 58 } 59 //小於則返回-1 60 else if(this.salary<o.getSalary()){ 61 return -1; 62 } 63 //相等則返回0 64 return 0; 65 } 66 }
(2)測試類,來查看是否按照自定義的屬性進行自然排序。
1 import java.util.ArrayList; 2 import java.util.Collections; 3 import java.util.List; 4 5 public class TestComparable { 6 7 public static void main(String[] args) { 8 //測試Comparable接口 9 Person p1=new Person("clyang",18,4000); 10 Person p2=new Person("messi",30,8000); 11 Person p3=new Person("ronald",32,9000); 12 Person p4=new Person("herry",19,7600); 13 Person p5=new Person("roben",35,7900); 14 15 //添加到集合 16 List<Person> list=new ArrayList<>(); 17 list.add(p1); 18 list.add(p2); 19 list.add(p3); 20 list.add(p4); 21 list.add(p5); 22 23 System.out.println("-----------------排序前-----------------"); 24 for (Person person : list) { 25 System.out.println(person); 26 } 27 28 //排序一般使用Collections.sort方法,或者使用Arrays.sort方法,按照比較的元素進行自然排序,即從小到大 29 Collections.sort(list); 30 31 System.out.println("-----------------排序后-----------------"); 32 for (Person person : list) { 33 System.out.println(person); 34 } 35 36 } 37 }
控制台輸出情況,發現正常的按照工資進行了自然排序,即升序排列。
使用Comparator
使用這個接口時,創建類的時候可以不實現接口,需要單獨創建一個類來實現這個接口。
(1)創建類

1 /** 2 * 實體類,不實現Comparable接口,使用單獨的Comparator接口 3 */ 4 public class Staff { 5 6 //屬性 7 private String name; 8 private int age; 9 private int salary; 10 11 public Staff(String name, int age, int salary) { 12 this.name = name; 13 this.age = age; 14 this.salary = salary; 15 } 16 17 public String getName() { 18 return name; 19 } 20 21 public void setName(String name) { 22 this.name = name; 23 } 24 25 public int getAge() { 26 return age; 27 } 28 29 public void setAge(int age) { 30 this.age = age; 31 } 32 33 public int getSalary() { 34 return salary; 35 } 36 37 public void setSalary(int salary) { 38 this.salary = salary; 39 } 40 41 @Override 42 public String toString() { 43 return "Staff{" + 44 "name='" + name + '\'' + 45 ", age=" + age + 46 ", salary=" + salary + 47 '}'; 48 } 49 }
(2)創建實現接口的類,重寫里面的比較方法,這屬於泛型在接口中的一種使用方法,即接口泛型是什么,實現類里面就是什么泛型。
1 import java.util.Comparator; 2 3 /** 4 * 單獨寫的比較器,實現Compartor接口 5 */ 6 public class StaffComparator implements Comparator<Staff> { 7 8 //不一定要自然排序即升序,可以反過來寫成降序 9 @Override 10 public int compare(Staff o1, Staff o2) { 11 //降序 12 /*if(o1.getSalary()>o2.getSalary()){ 13 return -1; 14 } 15 if(o1.getSalary()<o2.getSalary()){ 16 return 1; 17 } 18 return 0;*/ 19 20 //升序 21 /*if(o1.getSalary()>o2.getSalary()){ 22 return 1; 23 } 24 if(o1.getSalary()<o2.getSalary()){ 25 return -1; 26 } 27 return 0;*/ 28 29 //先按照年齡倒序排,如果年齡相等比較工資 30 if(o1.getAge()>o2.getAge()){ 31 return -1; 32 } 33 if(o1.getAge()<o2.getAge()){ 34 return 1; 35 } 36 //能到這里說明年齡相等,繼續比較工資 37 if(o1.getSalary()>o2.getSalary()){ 38 return 1; 39 } 40 if(o1.getSalary()<o2.getSalary()){ 41 return -1; 42 } 43 return 0; 44 } 45 }
測試類,來查看是否按照自己的要求來排序。
1 import java.util.ArrayList; 2 import java.util.Collections; 3 import java.util.Comparator; 4 import java.util.List; 5 6 public class TestComparator { 7 8 public static void main(String[] args) { 9 //測試Comparator接口 10 Staff p1=new Staff("clyang",18,4000); 11 Staff p2=new Staff("messi",30,8000); 12 Staff p3=new Staff("ronald",32,9000); 13 Staff p4=new Staff("herry",18,7600); 14 Staff p5=new Staff("roben",35,7900); 15 16 //添加到集合 17 List<Staff> list=new ArrayList<>(); 18 list.add(p1); 19 list.add(p2); 20 list.add(p3); 21 list.add(p4); 22 list.add(p5); 23 24 System.out.println("-----------------排序前-----------------"); 25 for (Staff staff : list) { 26 System.out.println(staff); 27 } 28 29 //排序,需要使用自定義比較類 30 Comparator myComparator=new StaffComparator(); 31 Collections.sort(list,myComparator); 32 33 System.out.println("-----------------排序后-----------------"); 34 for (Staff staff : list) { 35 System.out.println(staff); 36 } 37 } 38 }
控制台輸出情況,可以發現,先是按照年齡進行了倒排序,當排到clyang和herry的時候,由於年齡相同,因此繼續按照工資來升排序。
以上是兩種接口的使用方法,也是參考了博主的文章學習的,以后可以拿來用。
參考博文: