首页 > 技术文章 > Java对象比较-Comparable和Comparator接口使用

youngchaolin 2019-07-07 19:49 原文

最近在学习贪心算法和动态规划的过程中,里面有一段自然排序的操作,顺便简单了解一下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 }
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

推荐阅读