Java 基本类型比较 + 自定义类比较 + 对象的三种比较方法重写equals方法 /重写compareTo方法 /使用比较器


前言

本人是一个刚刚上路的IT新兵,菜鸟!分享一点自己的见解,如果有错误的地方欢迎各位大佬莅临指导,如果这篇文章可以帮助到你,劳请大家点赞转发支持一下!

上一篇文章,讲解了优先级队列,从这里开始就对插入的数据有要求了,那就是插入的数据必须可以比较,有优先级之分。并且以后要用到比较的地方也越来越多,所以今天就来讲一讲java对象的比较


一、PriorityQueue中插入对象

优先级队列在插入元素时有个要求:插入的元素不能是null或者元素之间必须要能够进行比较,那么我们要如何让插入的对象实现比较功能呢?

class Student {
    public String name;
    public int age;

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

public class Compare {
    public static void main(String[] args) {
        Student stu1 = new Student("小明",15);
        Student stu2 = new Student("小红",16);
        PriorityQueue<Student> priorityQueue = new PriorityQueue<>();
        priorityQueue.offer(stu1);
        priorityQueue.offer(stu2);

    }
}

运行上述代码时,会抛出运行时异常。
在这里插入图片描述
优先级队列底层使用堆,而向堆中插入元素时,为了满足堆的性质,必须要进行元素的比较,而此时Student是没有办法直接进行比较的,因此抛出异常。


二、数据的比较

1.基本类型的比较

在Java中,基本类型的对象可以直接比较大小。

    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        System.out.println(a > b);
        System.out.println(a < b);
        System.out.println(a == b);
        char c1 = 'A';
        char c2 = 'B';
        System.out.println(c1 > c2);
        System.out.println(c1 < c2);
        System.out.println(c1 == c2);
        boolean b1 = true;
        boolean b2 = false;
        System.out.println(b1 == b2);
        System.out.println(b1 != b2);

    }

2.自定义类的比较

class Student {
    public String name;
    public int age;

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

    public static void main(String[] args) {
        Student student1 = new Student("小明",15);
        Student student2 = new Student("小红",15);
        Student student3 = student1;

        //System.out.println(student1 > student2);
        //编译报错
        
        System.out.println(student1 == student2);
        //编译成功,打印false,因为student1和student2指向的是不同对象
        System.out.println(student1 == student3);
        //编译成功,打印true,因为student1和student2指向的是同一个对象
        
    }
  • Java中引用类型的变量不能直接按照 > 或者 < 方式进行比较。

那为什么 == 可以比较呢?
对于用户实现自定义类型,都默认继承自Object类,而Object类中提供了equal方法,而==默认情况下调用的就是equal方法,但是该方法的比较规则是:没有比较引用变量引用对象的内容,而是直接比较引用变量的地
址。
在这里插入图片描述
Object中equal的实现,是直接比较的是两个引用变量是否指向同一个地址


3.对象的比较

1.覆写基类的equals

class Student {
    public String name;
    public int age;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        //如果是同一个对象,返回true
        if (o == null || getClass() != o.getClass()) return false;
        //如果为空或不是同一类型,返回false
        Student student = (Student) o;
        //强转后,比较,这里认为只要姓名年龄相同就是一个人
        return age == student.age && Objects.equals(name, student.name);
    }
    
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {
        Student student1 = new Student("小明",15);
        Student student2 = new Student("小红",15);
        System.out.println(student1 == student2);//重写了equals,返回true
    }
}

覆写基类equal的方式虽然可以比较,但缺陷是:equal只能按照相等进行比较,不能按照大于、小于的方式进行比较。


2.基于Comparble接口类的比较

Comparble是JDK提供的泛型的比较接口类,源码如下:

在这里插入图片描述
compareTo返回一个值
这个值 < 0: 表示 this 指向的对象小于 o 指向的对象
这个值 == 0: 表示 this 指向的对象等于 o 指向的对象
这个值 > 0: 表示 this 指向的对象大于 o 指向的对象

对用用户自定义类型,如果要想按照大小与方式进行比较时:在定义类时,实现Comparble接口即可,然后在类中重写compareTo方法。

class Student implements Comparable<Student>{
    public String name;
    public int age;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }

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

    @Override
    public int compareTo(Student o) {
        //默认null最小
        if(o == null) {
            return 1;
        }

        //自己定义如何比较大小

        //return this.age - o.age;//凭年龄比较大小

        return this.name.compareTo(o.name);//凭姓名比较大小
        //String类自身就重写了compareTo方法,会优先调用自己的
    }

    public static void main(String[] args) {
        Student student1 = new Student("小明",15);
        Student student2 = new Student("小红",15);
        System.out.println(student1.compareTo(student2));
        // == 0,表示是一个同学
        // < 0,表示 student1 比较小
        // > 0,表示 student1 比较大
    }
}

Compareble是java.lang中的接口类,可以直接使用。

用这种写法呢,就将比较方式写死了,就不能再通过其他属性来比较了,侵略性强。


3.基于比较器比较

class Student {
    public String name;
    public int age;
}
//基于姓名的比较器
class NameComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.name.compareTo(o2.name);
    }
}

//基于年龄的比较器
class AgeComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.age - o2.age;
    }
}

可以看到两个比较器都实现了Comparator接口,并重写了compare方法。

  • 划重点,所以写比较器要实现Comparator接口,并重写compare方法!
    public static void main(String[] args) {
        Student student1 = new Student("小明",15);
        Student student2 = new Student("小红",15);

        //创建比较器对象
        AgeComparator ageComparator = new AgeComparator();
        NameComparator nameComparator = new NameComparator();

        int flg1 = ageComparator.compare(student1,student2);
        System.out.println(flg1);

        int flg2 = nameComparator.compare(student1,student2);
        System.out.println(flg2);
        // == 0,表示是一个同学
        // < 0,表示 p 比较小
        // > 0,表示 q 比较大
    }

虽然比较器,可以让你灵活的切换比较属性,但是切换比较属性也是需要改写代码的,所以比较器比较对代码的侵略性强

三种比较方式的特点

比较方式特点
覆写equals方法因为所有类都是继承自 Object 的,所以直接覆写即可,不过只能比较相等与否
需比较的类实现了Comparable接口,并重写了compareTo方法需要手动实现接口,侵入性比较强,但一旦实现,每次用该类都有顺序,属于内部顺序
创建比较器类,通过比较器对象进行比较(比较器类要实现Comparator接口并重写compare方法)需要实现一个比较器对象,对待比较类的侵入性弱,但对算法代码实现侵入性强

总结

例如:以上就是今天要讲的内容,本文分享了java中自定义类的三种比较方法,如果文章中有谬误,欢迎大家批评指正。

路漫漫,不止修身也养性。

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值