Java中Comparable与Comparator的区别

1. 两者对比

Comparable和Comparator都是用来实现集合中元素的比较、排序的。Comparable是在集合内部定义的方法实现的排序,位于java.util下。Comparator是在集合外部实现的排序,位于java.lang下。

  • Comparable是一个对象本身就已经支持自比较所需要实现的接口,如String、Integer等基本类型的包装类都自己就实现了Comparable接口,可完成比较大小操作。自定义类要在加入list容器中后能够排序,也可以实现Comparable接口,在用Collections类的sort方法排序时若不指定Comparator,那就以自然顺序排序。所谓自然顺序就是实现Comparable接口设定的排序方式。
  • Comparator是一个专用的比较器,当这个对象不支持自比较或者自比较函数不能满足要求时,可写一个比较器来完成两个对象之间大小的比较。Comparator体现了一种策略模式(strategy design pattern),就是不改变对象自身,而用一个策略对象(strategy object)来改变它的行为。总而言之Comparable是自已完成比较,Comparator是外部程序实现比较

2. 代码演示

// 测试Comparable
public class CompareTest {

    public static void main(String[] args) {

        ComparableImpl com1 = new ComparableImpl("name1",12);
        ComparableImpl com2 = new ComparableImpl("name1",11);
        ComparableImpl com13 = new ComparableImpl("name1",17);
        ArrayList lists = new ArrayList<>();
        lists.add(com1);
        lists.add(com2);
        lists.add(com13);
        Collections.sort(lists);
        lists.forEach(System.out::println);

    }

}
class ComparableImpl implements Comparable {

    String name;
    Integer age;

    public ComparableImpl(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    // 根据年龄进行对比
    @Override
    public int compareTo(Object obj) {
        if (obj instanceof ComparableImpl) {
            ComparableImpl another = (ComparableImpl) obj;
            if (this.age < another.age) {
                return -1;
            } else if (this.age.equals(another.age)) {
                return 0;
            } else {
                return 1;
            }
        }
        return 0;
    }

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

// 测试Comparator

// 不支持自比较的类
public class UnSpportSortObj {
    private String name;
    private Integer age;

    public UnSpportSortObj(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        UnSpportSortObj that = (UnSpportSortObj) o;
        return Objects.equals(name, that.name) &&
                Objects.equals(age, that.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

//  实现Comparator 的比较器
class ComparatorImpl implements Comparator {

    @Override
    public int compare(UnSpportSortObj o1, UnSpportSortObj o2) {

        return o1.getAge() - o2.getAge();

    }
}

// 测试
public class CompareTest {

    public static void main(String[] args) {

        // 使用Comparator接口进行排序
        ArrayList list2 = new ArrayList<>();
        ComparatorImpl comparator = new ComparatorImpl();

        UnSpportSortObj unSpportSortObj1 = new UnSpportSortObj("test1",25);
        UnSpportSortObj unSpportSortObj2 = new UnSpportSortObj("test2",18);
        UnSpportSortObj unSpportSortObj3 = new UnSpportSortObj("test3",36);
        UnSpportSortObj unSpportSortObj4 = new UnSpportSortObj("test4",5);

        list2.add(unSpportSortObj1);
        list2.add(unSpportSortObj2);
        list2.add(unSpportSortObj3);
        list2.add(unSpportSortObj4);

        list2.forEach(System.out::println);

    }

}

3. 两者差别

  • Comparator在集合(即你要实现比较的类)外进行定义的实现,而Comparable接口则是在你要比较的类内进行方法的实现。这样看来Comparator更像是一个专用的比较器。

  • Comparator实现了算法和数据的分离,从代码也可以看出,其实这和第一点是相辅相成的,因为Comparable依赖于某一个需要比较的类来实现。

  • Comparable支持自比较,自比较是指比如String等类里面本身就有CompareTo()方法,直接就可以进行String类对象的比较,这也可以从较之Comparator,Comparable中Arrays.sort()方法中只带数组参数的形式与书上例子更相似这点看出。

  • 从第3点延伸,我们可以看到当不满足于自比较函数,如String类时,我们试图改写规则要怎么办——通过Comparator因为它支持外比较,它是分离的。

  • 当一个又一个类设计完成后,或许我们最初没有设想到类的比较问题,而没使用Comparable接口,那我们之后可以通过Comparator来完成,而同时无需改变之前完成的类的构建。

  • 运用Arrays.sort()方法时,注意二者的参数不同,Comparator多了一个参数,这第二个参数是使用Comparator接口的那个被视为专用比较器的类的对象。

你可能感兴趣的:(Java中Comparable与Comparator的区别)