java比较器Comparator与Comparable

一、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的类

已知实现了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接口,并且定义了自然排序规则排序(字典序升序)

提高:
Comparator接口解释
Comparable接口解释

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值