比较器Comparator和Comparable的使用

当我们需要对一些数组和集合进行排序的时候,经常会用到Arrays.sort和Collections.sort方法。
但当sort里的数组或集合里的对象不适合用默认的比较方法时,我们就需要手动对排序方式重新定义。


比如,现在定义一个Person对象:

public class Person {

    private int id;
    private int age;

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

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }    

    @Override
    public String toString() 
        return "Person"+id+"->age:"+age;
    }
}

现在我们要对一堆person集合进行按年龄从小到大的排序或者年龄和id的和的大小的排序,这个时候默认的方法就无法实现我们的要求。


一般我们有两种方法来实现:

1.实现Comparable接口

让需要进行特殊排序的对象实现Comparable接口,并重写其中的compareTo方法

public class Person implements Comparable<Person>

compareTo中,如果想按从小到大的顺序排列,当符合小于规定时就返回-1。否则可以反向排序返回1。

@Override
public int compareTo(Person o) {
    if (age<o.age) {
        return -1;
    }else {
        return 1;
    }
}

测试:

public class ComparaTest {
    public static void main(String[] args) {
        List<Person> aList=new ArrayList<Person>();
        aList.add(new Person(1,13));
        aList.add(new Person(2, 42));
        aList.add(new Person(3, 5));
        aList.add(new Person(45, 32));
        aList.add(new Person(42, 88));
        aList.add(new Person(4, 5));
        System.out.println("排序前:");
        aList.stream().forEach(System.out::println);
        Collections.sort(aList);
        System.out.println("排序后:");
        aList.stream().forEach(System.out::println);
    }
}

输出

排序前:
Person1->age:13
Person2->age:42
Person3->age:5
Person45->age:32
Person42->age:88
Person4->age:5
排序后:
Person3->age:5
Person4->age:5
Person1->age:13
Person45->age:32
Person2->age:42
Person42->age:88

2.创建比较类继承Comparator

Comparator位于包java.util下,而Comparable位于包java.lang下。

创建一个比较类MyComparator:
这里我直接创建一个静态内部类用来比较,并定义为倒序

static class MyComparator implements Comparator<Person>{

    @Override
    public int compare(Person o1, Person o2) {
        if (o1.getAge()<o2.getAge()) {
            return 1;
        }else {
            return -1;
        }
    }
}

测试:

public static void main(String[] args) {
    List<Person> aList=new ArrayList<Person>();
    aList.add(new Person(1,13));
    aList.add(new Person(2, 42));
    aList.add(new Person(3, 5));
    aList.add(new Person(45, 32));
    aList.add(new Person(42, 88));
    aList.add(new Person(4, 5));
    System.out.println("排序前:");
    aList.stream().forEach(System.out::println);
    Collections.sort(aList,new MyComparator());
    System.out.println("排序后:");
    aList.stream().forEach(System.out::println);
}

输出:

排序前:
Person1->age:13
Person2->age:42
Person3->age:5
Person45->age:32
Person42->age:88
Person4->age:5
排序后:
Person42->age:88
Person2->age:42
Person45->age:32
Person1->age:13
Person4->age:5
Person3->age:5

另外,在leetcode第23题有配合优先级队列使用。