总结
Comparable 相当于 "内部比较器", 而 Comparator 相当于 "外部比较器".
- //Comparable example:
- Collections.sort(list);
- //Comparator example:
- // 通过 "比较器(AscAgeComparator)", 对 list 进行排序, AscAgeComparator 的排序方式是: 根据 "age" 的升序排序
- Collections.sort(list, new AscAgeComparator());
- // 通过 "比较器(DescAgeComparator)", 对 list 进行排序, DescAgeComparator 的排序方式是: 根据 "age" 的降序排序
- Collections.sort(list, new DescAgeComparator());
Comparable 是排序接口. 若一个类实现了 Comparable 接口, 就意味着 "该类支持排序". 即然实现 Comparable 接口的类支持排序, 假设现在存在 "实现 Comparable 接口的类的对象的 List 列表 (或数组)", 则该 List 列表(或数组) 可以通过 Collections.sort(或 Arrays.sort)进行排序. 此外,"实现 Comparable 接口的类的对象" 可以用作 "有序映射(如 TreeMap)" 中的键或 "有序集合(TreeSet)" 中的元素, 而不需要指定比较器.
Comparator 是比较器接口. 我们若需要控制某个类的次序, 而该类本身不支持排序(即没有实现 Comparable 接口); 那么, 我们可以建立一个 "该类的比较器" 来进行排序. 这个 "比较器" 只需要实现 Comparator 接口即可. 也就是说, 我们可以通过 "实现 Comparator 类来新建一个比较器", 然后通过该比较器对类进行排序.
Comparable 接口
Comparable 简介
Comparable 是排序接口.
若一个类实现了 Comparable 接口, 就意味着 "该类支持排序". 即然实现 Comparable 接口的类支持排序, 假设现在存在 "实现 Comparable 接口的类的对象的 List 列表 (或数组)", 则该 List 列表(或数组) 可以通过 Collections.sort(或 Arrays.sort)进行排序.
此外,"实现 Comparable 接口的类的对象" 可以用作 "有序映射(如 TreeMap)" 中的键或 "有序集合(TreeSet)" 中的元素, 而不需要指定比较器.
Comparable 定义
Comparable 接口仅仅只包括一个函数, 它的定义如下:
- package java.lang;
- import java.util.*;
- public interface Comparable<T> {
- public int compareTo(T o);
- }
说明:
假设我们通过 x.compareTo(y) 来 "比较 x 和 y 的大小". 若返回 "负数", 意味着 "x 比 y 小"; 返回 "零", 意味着 "x 等于 y"; 返回 "正数", 意味着 "x 大于 y".
Comparator 接口
Comparator 简介
Comparator 是比较器接口.
我们若需要控制某个类的次序, 而该类本身不支持排序(即没有实现 Comparable 接口); 那么, 我们可以建立一个 "该类的比较器" 来进行排序. 这个 "比较器" 只需要实现 Comparator 接口即可.
也就是说, 我们可以通过 "实现 Comparator 类来新建一个比较器", 然后通过该比较器对类进行排序.
Comparator 定义
Comparator 接口仅仅只包括两个个函数, 它的定义如下:
- package java.util;
- public interface Comparator<T> {
- int compare(T o1, T o2);
- boolean equals(Object obj);
- }
说明:
(01) 若一个类要实现 Comparator 接口: 它一定要实现 compareTo(T o1, T o2) 函数, 但可以不实现 equals(Object obj) 函数.
为什么可以不实现 equals(Object obj) 函数呢? 因为任何类, 默认都是已经实现了 equals(Object obj)的. Java 中的一切类都是继承于 java.lang.Object, 在 Object.java 中实现了 equals(Object obj)函数; 所以, 其它所有的类也相当于都实现了该函数.
(02) int compare(T o1, T o2) 是 "比较 o1 和 o2 的大小". 返回 "负数", 意味着 "o1 比 o2 小"; 返回 "零", 意味着 "o1 等于 o2"; 返回 "正数", 意味着 "o1 大于 o2".
实例 - Comparator 和 Comparable 比较
Comparable 是排序接口; 若一个类实现了 Comparable 接口, 就意味着 "该类支持排序".
而 Comparator 是比较器; 我们若需要控制某个类的次序, 可以建立一个 "该类的比较器" 来进行排序.
我们不难发现: Comparable 相当于 "内部比较器", 而 Comparator 相当于 "外部比较器".
我们通过一个测试程序来对这两个接口进行说明. 源码如下:
- import java.util.*;
- import java.lang.Comparable;
- /**
- * @desc "Comparator" 和 "Comparable" 的比较程序.
- * (01) "Comparable"
- * 它是一个排序接口, 只包含一个函数 compareTo().
- * 一个类实现了 Comparable 接口, 就意味着 "该类本身支持排序", 它可以直接通过 Arrays.sort() 或 Collections.sort()进行排序.
- * (02) "Comparator"
- * 它是一个比较器接口, 包括两个函数: compare() 和 equals().
- * 一个类实现了 Comparator 接口, 那么它就是一个 "比较器". 其它的类, 可以根据该比较器去排序.
- *
- * 综上所述: Comparable 是内部比较器, 而 Comparator 是外部比较器.
- * 一个类本身实现了 Comparable 比较器, 就意味着它本身支持排序; 若它本身没实现 Comparable, 也可以通过外部比较器 Comparator 进行排序.
- */
- public class CompareComparatorAndComparableTest{
- public static void main(String[] args) {
- // 新建 ArrayList(动态数组)
- ArrayList<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));
- // 打印 list 的原始序列
- System.out.printf("Original sort, list:%s\n", list);
- // 对 list 进行排序
- // 这里会根据 "Person 实现的 Comparable<String > 接口" 进行排序, 即会根据 "name" 进行排序
- Collections.sort(list);
- System.out.printf("Name sort, list:%s\n", list);
- // 通过 "比较器(AscAgeComparator)", 对 list 进行排序
- // AscAgeComparator 的排序方式是: 根据 "age" 的升序排序
- Collections.sort(list, new AscAgeComparator());
- System.out.printf("Asc(age) sort, list:%s\n", list);
- // 通过 "比较器(DescAgeComparator)", 对 list 进行排序
- // DescAgeComparator 的排序方式是: 根据 "age" 的降序排序
- Collections.sort(list, new DescAgeComparator());
- System.out.printf("Desc(age) sort, list:%s\n", list);
- // 判断两个 person 是否相等
- testEquals();
- }
- /**
- * @desc 测试两个 Person 比较是否相等.
- * 由于 Person 实现了 equals()函数: 若两 person 的 age,name 都相等, 则认为这两个 person 相等.
- * 所以, 这里的 p1 和 p2 相等.
- *
- * TODO: 若去掉 Person 中的 equals()函数, 则 p1 不等于 p2
- */
- private static void testEquals() {
- Person p1 = new Person("eee", 100);
- Person p2 = new Person("eee", 100);
- if (p1.equals(p2)) {
- System.out.printf("%s EQUAL %s\n", p1, p2);
- } else {
- System.out.printf("%s NOT EQUAL %s\n", p1, p2);
- }
- }
- /**
- * @desc Person 类.
- * Person 实现了 Comparable 接口, 这意味着 Person 本身支持排序
- */
- private static class Person implements Comparable<Person>{
- int age;
- String name;
- public Person(String name, int age) {
- this.name = name;
- this.age = age;
- }
- public String getName() {
- return name;
- }
- public int getAge() {
- return age;
- }
- public String toString() {
- return name + "-" +age;
- }
- /**
- * 比较两个 Person 是否相等: 若它们的 name 和 age 都相等, 则认为它们相等
- */
- boolean equals(Person person) {
- if (this.age == person.age && this.name == person.name)
- return true;
- return false;
- }
- /**
- * @desc 实现 "Comparable<String>" 的接口, 即重写 compareTo<T t > 函数.
- * 这里是通过 "person 的名字" 进行比较的
- */
- @Override
- public int compareTo(Person person) {
- return name.compareTo(person.name);
- //return this.name - person.name;
- }
- }
- /**
- * @desc AscAgeComparator 比较器
- * 它是 "Person 的 age 的升序比较器"
- */
- private static class AscAgeComparator implements Comparator<Person> {
- @Override
- public int compare(Person p1, Person p2) {
- return p1.getAge() - p2.getAge();
- }
- }
- /**
- * @desc DescAgeComparator 比较器
- * 它是 "Person 的 age 的降序比较器"
- */
- private static class DescAgeComparator implements Comparator<Person> {
- @Override
- public int compare(Person p1, Person p2) {
- return p2.getAge() - p1.getAge();
- }
- }
- }
运行程序, 输出如下:
- 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]
- eee - 100 EQUAL eee - 100
参考
详解 Java 中 Comparable 和 Comparator 接口的区别 https://www.jb51.net/article/123097.htm
来源: http://www.bubuko.com/infodetail-3357208.html