前言

Java中两个对象比较的方法常用在元素排序中,常用的两个接口分别是Comparable和Comparator,前者是自己和自己比,可以看做自营性质的比较,后者是第三方比较器,可以看做平台性质的比较器。

从词根上分析,Comparable是以-able结尾,表示它自身具备某种能力的性质,表明Comparable对象本身是可以与同类型进行比较的,它的比较方法是compareTo;而Comparator以-or结尾,表示自身是比较器的实践者,它的比较方法是compare。

Comparable接口

Comparable是内部比较器接口,唯一的一个方法是public int compareTo(T o);

Comparable示例

上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.example.test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CompareTest {

public static void main(String[] args) {

List list = new ArrayList<>();
list.add(new Dog(1,"小明"));
list.add(new Dog(2,"画画"));
list.add(new Dog(3,"黑黑"));
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i).toString());
}

//排序
Collections.sort(list);

System.out.println("-------排序之后------");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i).toString());
}

}

}

class Dog implements Comparable<Dog>{

public Dog(int age, String name) {
this.age = age;
this.name = name;
}

private int age;
private String name;


@Override
public String toString() {
return "Dog{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}

@Override
public int compareTo(Dog o) {
if(this.age>o.age){
return -1;
}
return 1;
}
}

我们自定义一个Dog类,实现了Comparable接口,泛型传入的是Dog类。重写compareTo方法:

1
2
3
4
5
6
public int compareTo(Dog o) {
if(this.age>o.age){
return 1;
}
return -1;
}

compareTo方法的逻辑是根据age进行比较,如果当前的age比传入的age大,则按从小到大的顺序排列。

运行结果:

1
2
3
4
5
6
7
Dog{age=1, name='小明'}
Dog{age=2, name='画画'}
Dog{age=3, name='黑黑'}
-------排序之后------
Dog{age=1, name='小明'}
Dog{age=2, name='画画'}
Dog{age=3, name='黑黑'}

如果需要从大到小排列,那么改成如下:

1
2
3
4
5
6
public int compareTo(Dog o) {
if(this.age>o.age){
return -1;
}
return 1;
}

运行结果:

1
2
3
4
5
6
7
Dog{age=1, name='小明'}
Dog{age=2, name='画画'}
Dog{age=3, name='黑黑'}
-------排序之后------
Dog{age=3, name='黑黑'}
Dog{age=2, name='画画'}
Dog{age=1, name='小明'}

Comparator接口

Comparator是外部的比较器,在JDK中Comparator最典型的应用是在Arrays.sort中作为比较器参数进行排序。

Comparator中有很多接口方法,有许多是Java8中引入的default默认方法实现。

int compare(T o1, T o2);是没有默认实现的一个接口,也是我们在实现比较功能时需要实现的一个方法。

Comparator示例

Dog类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Dog{

public Dog(int age, String name) {
this.age = age;
this.name = name;
}

int age;
String name;


@Override
public String toString() {
return "Dog{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}

}

定义外部比较器,实现Comparator接口:

1
2
3
4
5
6
7
8
9
10
11
12
class DogComparator implements Comparator<Dog> {
@Override
public int compare(Dog o1, Dog o2) {
if (o1.age>o2.age) {
return 1;
}
if (o1.age<o2.age) {
return -1;
}
return 0;
}
}

测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
	public static void main(String[] args) {
List list = new ArrayList<>();
list.add(new Dog(1,"小明"));
list.add(new Dog(2,"画画"));
list.add(new Dog(3,"黑黑"));
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i).toString());
}
//创建比较器实例
DogComparator comparator=new DogComparator();

//比较排序
Collections.sort(list,comparator);

System.out.println("-------排序之后------");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i).toString());
}

}

运行结果:

1
2
3
4
5
6
7
Dog{age=1, name='小明'}
Dog{age=2, name='画画'}
Dog{age=3, name='黑黑'}
-------排序之后------
Dog{age=1, name='小明'}
Dog{age=2, name='画画'}
Dog{age=3, name='黑黑'}

如果需要从大到小排列,需要改下compare方法里面的比较返回值:

1
2
3
4
5
6
7
8
9
10
11
12
class DogComparator implements Comparator<Dog> {
@Override
public int compare(Dog o1, Dog o2) {
if (o1.age>o2.age) {
return -1;
}
if (o1.age<o2.age) {
return 1;
}
return 0;
}
}

运行结果:

1
2
3
4
5
6
7
Dog{age=1, name='小明'}
Dog{age=2, name='画画'}
Dog{age=3, name='黑黑'}
-------排序之后------
Dog{age=3, name='黑黑'}
Dog{age=2, name='画画'}
Dog{age=1, name='小明'}

总结

主要研究了Comparable和Comparator两种来实现比较功能的方法。