结合TreeSet理解Comparable和Comparator的区别

Ref

https://www.cnblogs.com/xujian2014/p/5215082.html

疯狂java讲义第五版 p309、313

感谢

Comparable和Comparator的区别

  Comparable是排序接口,若一个类实现了Comparable接口,就意味着“该类支持排序”。而Comparator是比较器,我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。

  Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。

  两种方法各有优劣, 用Comparable 简单, 只要实现Comparable 接口的对象直接就成为一个可以比较的对象,但是需要修改源代码。 用Comparator 的好处是不需要修改源代码, 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了, 并且在Comparator 里面用户可以自己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。

Comparable可以理解为“自然排序”,Comparator可以理解为“定制排序”。

应用场合

SortedSet的子类TreeSet

以及其它的需要排序的集合应该都可以。

实例

定义Cat类,实现Comparable接口,实现自然排序

package com.lijunwei.nov14;

public class Cat implements Comparable<Cat> {
    private String name; 
    private int size;

    // 自然排序:猫的size越大,则表示猫越大
    @Override
    public int compareTo(Cat o) {
        if (this.size > o.size) {
            return 1;
        }
        if (this.size < o.size) {
            return -1;
        }
        return 0;
    }

    public Cat() {
    }

    public Cat(String name, int size) {
        this.name = name;
        this.size = size;
    }

    getters & setters...
    @Override
    public String toString() {
        return "Cat{" +
                "name='" + name + '\'' +
                ", size=" + size +
                '}';
    }
}

定制比较规则,实现定制排序

package com.lijunwei.nov14;

import java.util.Comparator;

public class CatComparator implements Comparator<Cat> {
    // 定制排序:猫的size越大,表示猫越小
    @Override
    public int compare(Cat o1, Cat o2) {
        if (o1.getSize() > o2.getSize()) {
            return -1;
        }
        if (o1.getSize() < o2.getSize()) {
            return 1;
        }
        return 0;
    }
}

编写测试类

package com.lijunwei.nov14;

import java.util.TreeSet;

public class CatTest {

    public static void main(String[] args) {
        // 创建一个自然排序的TreeSet,这里说是“自然”排序,是因为TreeSet已经实现了Comparable接口(实现了Comparable接口表示就具备了比较大小的能力)
        // TreeSet是SortedSet的实现类,因此插入数据时会自动排序,排序规则在compareTo方法中制定好了
        TreeSet<Cat> cats = new TreeSet<>();
        // 为集合中添加元素
        for (int i = 0; i < 5; i++) {
            cats.add(new Cat("c" + i, (int) (1 + Math.random() * 10)));
        }
        // 查看排序结果
        System.out.println("自然排序: "+cats);

        // 创建一个定制排序的TreeSet,这里说“定制”排序,是假设对Cat类内部定义的排序规则不满意,又不想修改Cat类的源码
        // 因此重新定义了一个CatComparator(猫类比较器),所以说是“定制”
        TreeSet<Cat> cats1 = new TreeSet<>(new CatComparator()); // 利用TreeSet的构造器传入Comparator对象
        for (int i = 0; i < 5; i++) {
            cats1.add(new Cat("c" + i, (int) (1 + Math.random() * 10)));
        }
        System.out.println("定制排序: "+cats1);
    }
}

运行结果

 

 需要注意的是,这里用的是set集合,因此在用循环为set添加元素时可能会因为用random方法生成的cat和已存在的cat“equals”,从而导致cat集合和cat1集合的元素个数不等,但这不是重点,重点是两个集合的排序规则相反,一个从小到大,另一个从大到小

 

 

posted @ 2019-11-15 09:40  什么能让我为谁停留  阅读(285)  评论(0编辑  收藏  举报