JDK1.8源码-11-Comparable和Comparator

JDK1.8源码-11-Comparable和Comparator

前序

本文,先介绍Comparable 和 Comparator两个接口,以及他们的差异;接着,通过示例,对它们的使用方法进行说明。

他们也是所属java.lang.util包下的接口。

1. Comparable

1.1 简介

  • Comparable 是排序接口。
  • 若一个类实现了Comparable 接口,就意味着“该类支持排序”。既然实现Comparable 接口的类支持排序,假设现在存在“实现Comparable 接口类的对象List列表【或者数组】”,则该列表(或数组)可以通过Collections.sort(或者Arrays.sort) 进行排序
  • 此外,“实现Comparable 接口的类的对象”可以用作有序映射(如TreeMap)中的键或有序集合(TreeSet) 中的元素,而不需要指定比较器。

1.2 定义

Comparable 接口仅仅只包括一个函数,它的定义如下:

1
2
3
4
5
6
package java.lang;
import java.util.*;

public interface Comparable<T> {
public int compareTo(T o);
}

说明:假设我们通过 x.compareTo(y) 来“比较x和y的大小”。

  • 若返回负数,说明 x < y
  • 若返回 0 ,说明 x = y
  • 若返回正数, 说明 x >y

2. Comparator

2.1 简介

  • Comparator 是 比较器接口
  • 若需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口);那么,我们可以建立一个“该类的比较器”来进行排序。
  • 这个比较器只需要实现Comparator 接口即可。
  • 也就是说,我们通过实现Comparator 类来新建了一个比较器,然后通过这个比较器对类进行排序

2.2 定义

1
2
3
4
5
6
7
8
package java.util;

public interface Comparator<T> {

int compare(T o1, T o2);

boolean equals(Object obj);
}

说明:

  • 若一个类要实现Comparator 接口,它一定要实现compareTo(T o1, T o2) 函数,但是可以不实现equals(Object obj)函数。

    • 为什么可以不用实现equals(Object obj) 函数呢?因为任何类,默认都是已经实现了equals(Object obj)的。Java中所有的类都是继承于java.lang.Object,在Object.java中实现了equals(Object obj) 函数;所以,其他所有的类也相当于实现了这个函数。
  • int compare(T o1, T o2) 是比较o1 和 o2 的大小

    • 若返回负数,说明o1 < o2
    • 若返回0,说明 o1 = o2
    • 若返回正数,说明 o1 > o2

3. Comparator 和 Comparable 比较

  • Comparable 是排序接口;若一个类实现了Comparable接口,就意味着“该类支持排序”。
  • Comparator 是比较器,若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。
  • 不难发现,Comparable 相当于内部比较器,Comparator 相当于外部比较器

我们通过一个测试程序来对这两个接口进行说明。源码如下:

3.1 Comparable 使用

  1. Person类定义
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
/** Person实现了Comparable接口,这意味着Person本身支持排序
*
*/
private static class Person implements Comparable<Person>{

String name;
int age;

// 实现 “Comparable<String>” 的接口,即重写compareTo<T t>函数。
// 这里是通过“person的名字”进行比较的
public int compareTo(Person person) {
return name.compareTo(person.name);
}

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

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}


// 比较两个Person是否相等:若它们的name和age都相等,则认为它们相等
boolean equals(Person person){
if (this.age == person.age && this.name == person.name){
return true;
}
return false;
}

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

说明:

  • Person 类代表一个人,Person类中有两个属性:age(年纪) 和 name“人名”。
  • Person 类实现了Comparable接口,因此它能被排序。
  1. 在main()函数中,我们创建Person的数组(list)
1
2
3
4
5
6
7
8
// 新建ArrayList(动态数组)
List<Person> list = new ArrayList<Person>();

// 添加对象到ArrayList中
list.add(new Person("ccc", 20));
list.add(new Person("AAA", 30));
list.add(new Person("bbb", 10));
list.add(new Person("ddd", 40));
  1. 接着我们打印list全部元素
1
2
// 打印list的原始序列
System.out.printf("Original sort, list:%s\n", list);
  1. 然后,我们通过Collections的sort()函数,对list进行排序
  • 由于Person类实现了Comparable接口,因此通过sort()排序的时候,会根据Person 支持的排序方式,即compareTo(Person peron) 所定义的规则进行排序,如下:
1
2
3
4
5
// 对list进行排序
// 这里会根据“Person实现的Comparable<String>接口”进行排序,
// 即会根据“name”进行排序
Collections.sort(list);
System.out.printf("Name sort, list:%s\n", list);

3.2 Comparator 使用

  1. 我们定义了两个比较器 AscAgeComparatorDescAgeComparator,来分别对Person进行 升序降低 排序。
1
2
3
4
5
6
7
8
9
10
11
/**
* @desc AscAgeComparator比较器
* 它是“Person的age的升序比较器”
*/
private static class AscAgeComparator implements Comparator<Person> {

@Override
public int compare(Person p1, Person p2) {
return p1.getAge() - p2.getAge();
}
}
1
2
3
4
5
6
7
8
9
10
11
/**
* @desc DescAgeComparator比较器
* 它是“Person的age的升序比较器”
*/
private static class DescAgeComparator implements Comparator<Person> {

@Override
public int compare(Person p1, Person p2) {
return p2.getAge() - p1.getAge();
}
}
  1. 通过自定义比较器AscAgeComparator 对list按照年龄升序排序
1
2
3
// 通过“比较器(AscAgeComparator)”,对list进行排序
Collections.sort(list,new AscAgeComparator());
System.out.printf("Asc(age) sort, list:%s\n", list);
  1. 通过自定义比较器DescAgeComparator 对list按照年龄降序排序
1
2
3
// 通过“比较器(DescAgeComparator)”,对list进行排序
Collections.sort(list,new DescAgeComparator());
System.out.printf("Desc(age) sort, list:%s\n", list);

结果如下:

1
2
3
4
Original  sort, list:[ccc - 20, AAA - 30, bbb - 10, ddd - 40]
Name sort, list:[AAA - 30, bbb - 10, ccc - 20, ddd - 40]
Asc(age) sort, list:[bbb - 10, ccc - 20, AAA - 30, ddd - 40]
Desc(age) sort, list:[ddd - 40, AAA - 30, ccc - 20, bbb - 10]
打赏
  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2019-2022 Zhuuu
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信