一、Comparable:

 Comparable是java提供的一个排序接口,若一个类实现了Comparable接口,就意味着该类能够实现排序。实现了该接口的对象,可以通过Collections.sort,或者Arrays.sort来进行排序。

1.定义:

Comparable是存在 import  java.lang.Comparable中的,打开源码我们可以看到它的定义如下:

public interface Comparable<T> {       
   public int compareTo(T o);
}
->自定义泛型<T>指的是可以和当前类型进行比较的类型
->接口内只含有一个compareTo(T o)方法,当o小于、等于、或者大于当把对象时返回:正数、0、或负数

2.使用:

(1)假设一个Student类

package IMUHERO;

public class Student
{
    private String name;
    private int scores;
    public Student(String name, int age)
    {
        super();
        this.name = name;
        this.scores = age;
    }

    public String getName()
    { return name; }
    
    public int getScores()
    { return scores; }
    
}

(2)如何比较两个Student之间的大小呢?

package IMUHERO;
import java.lang.Comparable;
public class Student implements Comparable<Student>
{
    private String name;
    private int scores;
    public Student(String name, int age)
    {
        super();
        this.name = name;
        this.scores = age;
    }

    public String getName()
    { return name; }

    public int getScores()
    { return scores; }

    @Override
    public int compareTo(Student o) {
        return this.scores-o.scores;
        //此处就定义了一种从小到大排序成绩的方法
        //也可以定义从大到小:return this.scores-o.scores;
    }
}

->我们只需要implements Comparable<Student>,并且@override compareTo(Student o)就可以。

3.接下去我们使用几个测试用例来看一下效果:

public static void main(String[] args) {
        Student[] students=new Student[]{new Student("张小二",95),new Student("李一一",90)};
        System.out.println("排序前的先后顺序是:");
        for (Student stu:students){
            System.out.println("姓名:"+stu.getName()+" 成绩:"+stu.getScores());
        }
        Arrays.sort(students);
        System.out.println("排序后的先后顺序是:");
        for (Student stu:students){
            System.out.println("姓名:"+stu.getName()+" 成绩:"+stu.getScores());
        }

    }

 ->结果

appcompat gradle plugin java对应关系 comparable java_比较器

二、Comparator:

Comparator是java提供的一个比较接口,当我们需要对一个类进行排序,而该类本身不支持排序(即没有实现Comparable接口),那么我们可以通过新建一个比较器来进行排序。

新建比较器的过程一般是先新建一个类,实现Comparator接口,并重写compare(T o1,T o2)方法。

1.定义:

Comparator是存在 import  java.util.Comparator中的,打开源码我们可以看到它的定义如下:

public interface Comparator<T> {     
  int compare(T o1, T o2);
  boolean equals(Object obj);
}
->自定义泛型<T>指的是将要比较的类型
->该接口包含有两个方法,实现该接口必须要重写compare(T O1,T O2)方法,但是不一定要重写equals(Object obj)方法
->compare方法返回负数、0、正数,依次代表o1<o2,o1==o2,o1>o2

 

2.使用:

(1)上文中的Student仍旧存在

package IMUHERO;

public class Student
{
    private String name;
    private int scores;
    public Student(String name, int age)
    {
        super();
        this.name = name;
        this.scores = age;
    }

    public String getName()
    { return name; }
    
    public int getScores()
    { return scores; }
    
}

(2)如何比较两个Student之间的大小呢?

class myCompare implements Comparator<Student>{
    @Override
    public int compare(Student o1, Student o2) {
        return o1.getScores()-o2.getScores();
        //此处就定义了一种从小到大排序成绩的方法
        //也可以定义从大到小:return o1.scores-o2.scores;
    }
}

新建一个myCompare比较器 

->在比较器中:我们只需要implements Comparator<Student>,并且@override compare(Student o1,Student o2)就可以。

 

3.接下去我们使用几个测试用例来看一下效果:

(1)如果按照刚刚的代码进行测试,就会报错,显示找不到比较方法

appcompat gradle plugin java对应关系 comparable java_java_02

(2)修改一下代码,添加new myCompare

Arrays.sort(students,new myCompare());
public static void main(String[] args) {
        Student[] students=new Student[]{new Student("张小二",95),new Student("李一一",90)};
        System.out.println("排序前的先后顺序是:");
        for (Student stu:students){
            System.out.println("姓名:"+stu.getName()+" 成绩:"+stu.getScores());
        }
        Arrays.sort(students,new myCompare());
        System.out.println("排序后的先后顺序是:");
        for (Student stu:students){
            System.out.println("姓名:"+stu.getName()+" 成绩:"+stu.getScores());
        }

    }

 ->即可得到正确的结果

appcompat gradle plugin java对应关系 comparable java_System_03

三、二者的区别

1.Comparable接口需要从源码(示例中是Student类)中去修改compareTo方法

2.Comparator可以通过自己新建一个比较器,从外部定义或者修改类的比较方法

3.简言之,Comparable是从内部修改,Comparator是从外部修改

注:

如果源码是自定义的,可以直接实现Comparable,这样很方便,代码简洁;

但是源码如果是系统的,比如我们要改变priorityQueue(优先队列)的先后顺序为从大到小(源码是从小到大),那么从外部去实现一个自定义比较器会是一个更好的选择。