Comparable和Comparator

1、Comparable接口

1
2
3
4
5
package java.lang;
import java.util.*;
public interface Comparable<T> {
public int compareTo(T o);
}

列表和数组中的对象,如果实现了Comparable接口,就能直接通过Collections.sort(List)Arrays.sort(Object[])进行排序。

实现了Comparable接口的对象,可以用作SortedMap中的键或SortedSet排序集中的元素,且无需指定 Comparator比较器。

比如 Integer 类:

1
2
3
4
5
6
7
8
9
10
11
public final class Integer extends Number implements Comparable<Integer> {
...
public int compareTo(Integer anotherInteger) {
return compare(this.value, anotherInteger.value);
}
// 根据元素大小比较,-1 小于 anotherInteger,0 等于,1 大于
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
...
}

使用自然排序需要类实现 Comparable,并且在内部重写 comparaTo 方法。

2、Comparator比较器

1
2
3
4
5
6
7
package java.util;
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
// 以及一些 default 方法:实现类不必覆写default方法。
// 以及一些 static 静态方法
}

我们如果想让类保持它的原貌,不想修改类使主动实现 Comparable 接口,但又需要它们之间进行比较,这就需要用到Comparator接口。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*User类*/
@Data
public class User implements Serializable {
private static final long serialVersionUID = -2505035389234495754L;
private int userId;
private Integer age;

public User(int userId, Integer age) {
this.userId = userId;
this.age = age;
}
}

/*自定义User类的比较器*/
//创建一个 Comparator 接口的实现类,在 compare 方法中针对自定义类写排序规则
public static class UserComparator implements Comparator<User> {
@Override
public int compare(User o1, User o2) {
if (o1 == null || o2 == null) {
return 0;
}
return o1.getAge() - o2.getAge();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
/*将自定义比较器 UserComparator 对象作为参数传递给排序类的某个方法。*/
public class ComparatorTest {
public static void main(String[] args) {
User user1 = new User(1, 18);
User user2 = new User(2, 15);
List<User> userList = new ArrayList<>();
userList.add(user1);
userList.add(user2);
//userList.sort(new UserComparator());
Collections.sort(userList,new UserComparator());
System.out.println(userList);
}
}

3、两者比较:

  • 使用自然排序需要类实现 Comparable,并且在内部重写 comparaTo 方法。

  • Comparator 则是在外部制定排序规则,然后作为排序策略参数传递给某些类,比如 Collections.sort ()Arrays.sort(),或者一些内部有序的集合(比如 SortedSetSortedMap 等)。

在定义比较方法中,需要考虑 null 的情况。