java 基础 之 Comparable与Comparator

曾经去一家公司面试,上来第一道问题就是问这个,原题目大概是:给你一个Student类 实现Comparable接口,如何写这个compareTo方法。

当时很蒙,因为长时间的CURD,只是用的比较多,但是基础相对薄弱,结果必然是铩羽而归。

为什么你经验很多了还会问这样的问题?

因为经验越是多,越应该不只停留在表面上,底层以及基础知识必须扎实,这简直是铁律。

不多说了,把排序比较器总结如下:

Java的排序一般是2种,Comparable与Comparator。

1、Comparable

import java.util.Comparator;
import java.util.Objects;
import java.util.TreeSet;

/**
 * Comparable演示
 */
public class Student implements Comparable<Student> {
    private String name;
    private Integer age;

    public Student() {
    }

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

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    @Override
    public boolean equals(Object o) {
        // 如果两个对象的引用地址相等,则返回true。
        if (this == o) return true;
        // 如果被比较的元素为空或者被比较的对象类型与当前类类型不一致则返回false.
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        // 如果不是同一个对象,但是类不为空且是同一类型,则比较名字和年龄是否相同
        return Objects.equals(name, student.name) && Objects.equals(age, student.age);
    }

    @Override
    public int compareTo(Student o) {
        // 如果年龄相同,则再比较名字
        int a = this.age - o.getAge();
        // 如果年龄相同,则对比名字,如果名字compareTo相同则返回0
        int r = (a == 0 ? this.name.compareTo(o.getName()) : a);
        return r;
    }

    public static void main(String[] args) {
        // 构建TreeSet实例时,使用了无参构造函数,则使用的排序是自然排序。
        // TreeSet中的对象必须实现Comparable接口,重写compareTo()方法。
        Student s1 = new Student("xiaobu", 12);
        Student s2 = new Student("pang", 12);
        TreeSet<Student> treeSet = new TreeSet<>();
        treeSet.add(s2);
        treeSet.add(s1);
        System.out.println(JSON.toJSON(treeSet));
    }
}

小结:Comparable的使用场景是被某个类实现。那么凡是这个类的对象都具有了比较的功能。(毕竟对象类型与基础数据类型不同,天生没有自己的比较规则,需要后天给它实现)

实现Comparable接口,必须要重写Comparable的compareTo()方法与当前对象的hashCode()equals()方法。

缺点:如果实体类比较多,则产生大量的额外工作量。

2、Comparator

import java.util.Comparator;

/**
 * Student使用比较器Comparator
 */
public class Student {
    private String name;
    private int age;
    public Student(String name, int age){
        this.name = name;
        this.age = age;
    }
    // getter setter ....
    public static void main(String[] args) {
        TreeSet<Student> students = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                // 如果年龄相同,则再比较名字
                int a = o1.age - o2.getAge();
                // 如果年龄相同,则对比名字,如果名字compareTo相同则返回0
                int r = (a == 0 ? o1.name.compareTo(o2.getName()) : a);
                return r;
            }
        });
    }
}

小结:Comparator的使用场景是临时的,不需要提前定义一个比较器,也跟具体的类没有关系。即用时才实现一下比较规则。

优点:用到比较器的类比较是少数,如果用Comparable,那么有100个实体类 这100个实体类都要实现Comparable且重写compareTo()方法与当前对象的hashCode()equals()方法。费时费力。

而Comparator则不需要这样。谁用到比较器谁自己临时写一个就可以。

没有绝对的好与坏,根据实际需要来决定即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值