Java中Comparable与Comparator的区别

我们先来看这两个接口的定义:

//Comparable
package java.lang;
import java.util.*;

/**
This interface imposes a total ordering on the objects of each class that implements it.  This ordering is referred to as the class's <i>natural ordering</i>, and the class's <tt>compareTo</tt> method is referred to as its <i>natural comparison method</i>.<p>Lists (and arrays) of objects that implement this interface can be sorted automatically by {@link Collections#sort(List) Collections.sort} (and {@link Arrays#sort(Object[]) Arrays.sort}).
 */
public interface Comparable<T> {
    public int compareTo(T o);
}
//Comparator
package java.util;

/**
A comparison function, which imposes a <i>total ordering</i> on some collection of objects.  Comparators can be passed to a sort method (such as {@link Collections#sort(List,Comparator) Collections.sort} or {@link Arrays#sort(Object[],Comparator) Arrays.sort}) to allow precise control over the sort order.
*/
public interface Comparator<T> {
    int compare(T o1, T o2);

    boolean equals(Object obj);
}

这里顺便摘了一些注释过来,可以从注释的描述上看到两个接口的作用差不多,都是用作比较或排序,并且都可以用于Collections.sort和Arrays.sort。

当然它们也有一些区别:

  • Comparable是java.lang下面的,而Comparator是java.util下面的。
  • Comparable可以说是内比较器,是需要比较的类自己去实现这个接口的方法,调用的时候也是调用类的compareTo方法;Comparator是外比较器,需要为比较的类专门写一个比较器并实现这个接口的方法,调用的时候也是调用比较器的compare方法。这里我们看到其实还有一个equals方法,但实际上我们不实现它也不会报错,这是为什么呢?因为Object类实现了该方法,我们知道,Object是所有类的父类,所以我们自己写的类也隐式地实现了该方法。

下面用具体的代码来看一下。

我们写一个简单的Person类,包含姓名和年龄。想要按照年龄大小排序。

public class Person {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

现在来实现Comparable接口,注意如果要实现从小到大排序的话,需要保证自身比传入对象小的时候返回负数,相等的时候返回0,比传入对象大的时候返回整数。如果弄反的话会变成从大到小排序。

public class Person implements Comparable<Person> {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public int compareTo(Person p) {
        return this.age - p.getAge();
    }

    public static void main(String[] args) {
        Person[] people = new Person[]{new Person("xiaoming", 20), new Person("xiaohong", 15), new Person("xiaowei", 10)};
        System.out.println("\n排序前");
        for (Person person : people) {
            System.out.print(person.getName() + ":" + person.getAge());
        }
        Arrays.sort(people);
        System.out.println("排序后");
        for (Person person : people) {
            System.out.print(person.getName() + ":" + person.getAge());
        }
    }
}

输出结果:
输出结果

接下来试试Comparator,我们需要写一个类实现这个接口。同样是需要注意如果要实现从小到大排序,需要保证o1比o2小的时候返回负数。

public class PersonComparator implements Comparator<Person> {

    @Override
    public int compare(Person o1, Person o2) {
        return o1.getAge() - o2.getAge();
    }
}
public class Person {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public static void main(String[] args) {
        Person[] people = new Person[]{new Person("xiaoming", 20), new Person("xiaohong", 15), new Person("xiaowei", 10)};
        System.out.println("排序前");
        for (Person person : people) {
            System.out.print(person.getName() + ":" + person.getAge());
        }
        Arrays.sort(people, new PersonComparator());
        System.out.println("\n排序后");
        for (Person person : people) {
            System.out.print(person.getName() + ":" + person.getAge());
        }
    }
}

输出结果:
输出结果

可以看到调用Arrays.sort的时候额外传入了我们自定义的比较器。

那什么时候该用Comparable什么时候该用Comparator呢?个人认为并没有什么差别。如果想实现类的自比较或调用Arrays.sort等方法时或希望传入SortedMap等有序结构时可以自动排序的时候,可以在类中实现Comparable接口;当无法修改一个类的代码或类自身已经实现了Comparable接口的时候,我们可以选择实现一个Comparator比较器从外部去比较,比如对于Integer类,我们如果想按照绝对值大小排序的话,就可以实现一个Comparator。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值