最近在学习贪心算法和动态规划的过程中,里面有一段自然排序的操作,顺便简单了解一下Java中对象比较后排序要使用的两个接口:Comparable和Comparator。如果是数字,直接比较就行,但是如果是对象,如何比较后排序呢?就需要用到这两个接口了,并且将自己定义的类作为参数传入接口泛型,在接口里重写比较方法,将自己要选择排序的类属性添加到比较条件中去。
接口主要区别
(1)Comparable接口是在java.lang下,Comparator接口是在java.lang下。
(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 }View Code
(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的时候,由于年龄相同,因此继续按照工资来升排序。
以上是两种接口的使用方法,也是参考了博主的文章学习的,以后可以拿来用。
参考博文:
(1)https://www.cnblogs.com/Kevin-mao/p/5912775.html
(2)https://www.cnblogs.com/youngchaolin/p/11029505.html