欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java比较器Comparator与Comparable

程序员文章站 2022-03-10 17:07:01
...

一、List容器排序方法

<T> void java.util.Collections.sort(List<T> list)
<T> void java.util.Collections.sort(List<T> list, Comparator<? super T> c)

二、实现Comparator接口,按照自定义规则进行排序

1.定义一个用户类

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

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "\n User [name=" + name + ", age=" + age + "]";
    }
}

2.实现Comparator接口,按照age升序排列

import java.util.Comparator;
public class ComparatorByAge implements Comparator<User> {

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

        int o1age = o1.getAge();
        int o2age = o2.getAge();

        if (o1age < o2age) {
            return -1;
        } else if (o1age == o2age) {
            return 0;
        } else {
            return 1;
        }
    }

}

3.排序

public static void main(String args[]) {
        List<User> users = new ArrayList<>();
        users.add(new User("father", 36));
        users.add(new User("mother", 36));
        users.add(new User("grandmother", 50));
        users.add(new User("me", 12));
        System.out.println("before sorted:" + users);
        Collections.sort(users, new ComparatorByAge());
        System.out.println("after sorted:" + users);
    }
    /* 输出结果
       before sorted:[
       User [name=father, age=36], 
       User [name=mother, age=36], 
       User [name=grandmother, age=50], 
       User [name=me, age=12]]
       after sorted:[
       User [name=me, age=12], 
       User [name=father, age=36], 
       User [name=mother, age=36], 
       User [name=grandmother, age=50]]
     */

二、需要排序的类直接实现Comparable接口。定义一个且仅一个排序规则

1.定义一个学生类,基于分数升序排序

public class Student implements Comparable<Student> {
    private String name;
    private Integer score;

    public Student(String name, Integer score) {
        this.name = name;
        this.score = score;
    }

    @Override
    public int compareTo(Student o) {
        return this.score.compareTo(o.score);
    }

    @Override
    public String toString() {
        return "\n Student [name=" + name + ", score=" + score + "]";
    }
}

2.排序

public static void main(String args[]) {
        List<Student> list = new ArrayList<>();
        list.add(new Student("学霸", 100));
        list.add(new Student("学渣", 60));
        list.add(new Student("普通", 80));
        Collections.sort(list);
        System.out.println(list);

        Set<Student> treeset = new TreeSet<>();
        treeset.add(new Student("学霸", 100));
        treeset.add(new Student("学渣", 60));
        treeset.add(new Student("普通", 80));
        System.out.println(treeset);
    }
    /*  [
        Student [name=学渣, score=60], 
        Student [name=普通, score=80], 
        Student [name=学霸, score=100]]
        [
        Student [name=学渣, score=60], 
        Student [name=普通, score=80], 
        Student [name=学霸, score=100]]
     */

总结:对象T排序规则有时会有多个,可以定义多个实现了Comparator<T>接口的比较器,调用Collections.sort(List<T> list, Comparator<? super T> c),指定比较器进行排序。
当对象T一般只有一个排序规则时,或者一般是自然排序规则的时候,对象直接实现Comparable接口,调用Collections.sort(List<T> list)方法排序,对于TreeSet这样的有序集合会自动按照定义的规则排序。
相对来说Comparator就像一个很灵活的工具,需要什么样的排序规则立马定义一个。而Comparable更像是对这个类T的补充,明确之间的排序规则。当用到排序时就默然按照这样的规则执行。

一般某规则排序只需要用一次的话,可以通过一个实现了Comparator的匿名内部类达到排序的目的

    public static void main(String args[]) {
        List<User> users = new ArrayList<>();
        users.add(new User("father", 36));
        users.add(new User("mother", 36));
        users.add(new User("grandmother", 50));
        users.add(new User("me", 12));
        System.out.println("before sorted:" + users);
        Collections.sort(users, new Comparator<User>() {
            @Override
            public int compare(User o1, User o2) {
                Integer a = o1.getAge();
                Integer b = o2.getAge();
                return a.compareTo(b);
            }
        });
        System.out.println("after sorted:" + users);
    }
    // before sorted:[
    // User [name=father, age=36],
    // User [name=mother, age=36],
    // User [name=grandmother, age=50],
    // User [name=me, age=12]]
    // after sorted:[
    // User [name=me, age=12],
    // User [name=father, age=36],
    // User [name=mother, age=36],
    // User [name=grandmother, age=50]]

上段代码中的a.compareTo(b) 返回-1、0、1,因为Integer实现了Comparable接口。

联想
1.已知实现了Comparable的类

java比较器Comparator与Comparable

2.常见类实现Comparable接口

    //Integer实现Comparable接口中的compareTo方法源码

    public int compareTo(Integer anotherInteger) {
        return compare(this.value, anotherInteger.value);
    }
    public static int compare(int x, int y) {
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
    }


    //String实现Comparable接口中的compareTo方法源码

     public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }

官方解释:Comparable接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。
也就是说java提供的已经实现了Comparable接口的类的排序一般都是自然排序。

这也就是为什么
Collections.sort(List<String> list)
Collections.sort(List<Integer> list)可以对list进行排序,不用指定特定的比较器,因为String、Integer这些类已经实现了Comparable接口,并且定义了自然排序规则排序(字典序升序)

提高:
java比较器Comparator与Comparable
java比较器Comparator与Comparable