1、前言
对于Java中的对象,我们只能使用基本运算符==、!=来判断一下地址是否相等,不能使用>、<来比较大小。但是在实际的开发中,我们需要对对象进行排序,也就是比较大小,那么应该如何实现呢?这就涉及到了Java中的两个常用的接口Comparable
2、Comparable接口
Comparable是一个基于排序接口,它是自然排序。该接口中只有一个compareTo(Obj o)方法,用于给一个类的多个实例比较大小,进而完成排序。也就是说某个类实现了Comparable接口,就意味着该类支持排序。通过实现类重写compareTo(Obj o)方法,从而规定多个实例的自然顺序,然后使用Arrays.sort 或Collections.sort 方法对数组对象或List对象进行排序。
用String举一个简单的例子:
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当前对象)大于被比较者(即compareTo方法里面的形参),则返回正整数。
②、如果比较者小于被比较者,那么返回负整数。
③、如果比较者等于被比较者,那么返回零。
自定义的类是无法排序的,但是通过实现Comparable接口之后就可以实现,然后通过Arrays.sort 或Collections.sort 方法排序。我们来看一个自己定义的类怎么使用Comparable接口进行排序:
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)方法,然后我们按照名字排序,可以发现它默认的排序方式是升序,如果要降序则可以在返回值前面加一个负号。
3、Comparator接口
Comparator也是一个排序接口,它和Comparable功能是一样的,但是它是定制排序。怎么来理解定制排序呢?如果某个类没有实现Comparable接口,而该类本身是不支持排序的,那么我们就可以使用Comparator来进行排序,或者我们自定义类实现了Comparable接口后,但是自定义类的代码不能再更改了,这时需要改变comparaTo(Obj o)方法中排序的方式,此时也可以选择定制排序Comparator。Comparator接口中有一个compare(T o1, T o2)方法和compareTo(Obj o)类似,定义排序的规则一样:
o1>o2,返回值为正整数。
o1 o1=o2,返回值为零。 同样使用String简单举例: 我们知道接口是不能被实例化的,这里是匿名内部类的知识,可以自行去度娘寻找答案。 自定义类使用Comparator进行排序: 程序运行结果: 这样就使用Comparator定制排好序了。 小结一下Comparable和Comparator的使用和区别: ①、Comparable是java.lang包下的,而Comparator是java.util包下的。 ②、Comparable可以看做是内部比较器,而Comparator是外部比较器。 ③、Comparable是自然排序,Comparator是定制排序。 ④、如果某个类没有实现Comparable接口,而该类本身是不支持排序的,那么我们就可以使用Comparator来进行定制排序。 ⑤、或者我们自定义类实现了Comparable接口后,但是自定义类的代码不能再更改了,这时需要改变compareTo(Obj o)方法中排序的方式,此时也可以选择定制排序Comparator。 这两种方法各有优劣:某个类实现了Comparable接口后,在任何地方都可以比较大小,但是有时候需要修改其比较的方式,则需要修原有的代码。而用Comparator的好处就是不需要修改原有代码, 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了, 并且在Comparator 里面用户可以自己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。 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
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
4、小结