equal方法和Comparable接口和Compartor接口(很详细)

一.equal方法

        1.1 引出equal方法

        

             思考一下输出语句输出的内容。

        

        

在这段代码中:

  • System.out.println(s1 == s2); 输出 false 。因为使用 new 关键字创建的 String 对象会在堆内存中开辟新的空间,所以 s1 和 s2 是两个不同的对象,它们的引用不同。

  • System.out.println(s1 == s3); 输出 false 。s1 是通过 new 创建的对象,存放在堆内存中;而 s3 是直接使用字符串常量创建的,会先在字符串常量池中查找是否已经存在 "abc" ,如果存在则直接引用,否则创建并放入常量池。所以 s1 和 s3 的引用不同。

  • System.out.println(s3 == s4); 输出 true 。因为 s3 和 s4 都是直接使用字符串常量创建的,当在常量池中已经存在 "abc" 时,它们会引用同一个常量池中的对象,所以引用相同。

那么我们如果想比较两个new对象的内容应该怎么比较呢?

        我们就要用到equal方法了。

        

        equal是比较内容的。

这是方法内部的原理。

        谁调用了equal谁就是this。


1.2:equal的延深

        1.2.1 问题

        上面的问题我们解决了,如果我们想比较两个类对象的内容应该怎么比较呢?

        

        打印出了false。

        为什么呢?

        这是因为在默认情况下,如果您没有在自定义的 testdemo3 类中重写 equals 方法,那么使用的是从 Object 类继承来的 equals 方法,而该方法默认是通过比较对象的引用是否相等来判断是否相等的。

        在您的代码中,testdemo3 和 testdemo31 是两个通过 new 操作符创建的不同对象,它们的引用不同,所以 equals 方法返回 false 。

        那String也是创建新对象,引用也不同,为什么用equal就会打印出来true呢?

        当使用 equals 方法比较两个 String 对象时,如果它们的内容相同,就会打印 true ,这是因为 String 类已经重写了 Object 类的 equals 方法。


        1.2.2 重写equal方法

        那我们应该怎么重写equal方法呢?

        

        用这个方法就可以了,getClass()!= o.getClass():获取当前对象的类对象(通过 getClass() 方法),并与传入对象 o 的类对象进行比较。如果两个类对象不相同,说明它们不是同一类型的对象,也就不可能相等,直接返回 false 。

        

        为什么还要重写hashCode方法呢?

        1.一致性原则:根据 Java 的约定,如果两个对象通过 equals 方法比较相等,那么它们的 hashCode 值也必须相等。反之,如果两个对象的 hashCode 值不同,那么它们一定不相等;但如果 hashCode 值相同,它们不一定相等(因为可能存在哈希冲突)。


二.Comparable接口

        2.1 引出Comparable接口

        

        

        现在我想比较一下xiaoming和xiaohong谁的年龄大,此时就可以用到Comparable接口中的compareTo方法了。

        

        接接口后面的<>里面填上需要用到的类,还需要重写compareTo方法。

        此时就可以比较了

        

        通过返回的值可知,student11的年龄大于student1的年龄。


       2.2 详细用法

        接下来我们再来完成一下学生年龄的排序。

        

        myarray中的参数是表示实现这个接口的类数组。

        结果

        比较name无意义我就不再写了。


        2.3 优点:

        1.        内聚性:将比较逻辑直接嵌入到要比较的类中,使相关的功能在同一个地方,增强了代码的内聚性和封装性。

        2.        自然排序:定义了对象的自然排序方式,使得在需要对该类型的对象进行排序时,无需额外提供比较器,使用起来更加直观和方便。

        3.        更加的通俗易懂。


2.4 缺点:

        1.灵活性受限:一旦确定了类实现 Comparable 接口的比较逻辑,就难以在不同的上下文中更改比较方式。如果后续有新的比较需求,可能需要修改类的代码,这可能会影响到使用该类的其他部分代码。

        2. 单一比较规则:一个类只能定义一种自然的比较规则。如果在不同场景下需要根据不同的属性或规则进行比较,就无法直接使用 Comparable 提供的默认比较方式。

        3. 类的修改影响范围:如果一个被广泛使用的类修改了其 Comparable 的比较逻辑,可能会导致所有依赖于该比较逻辑的代码都受到影响,需要进行相应的调整和测试。


三.Compartor接口

        3.1 引出Compartor接口

        为了解决Comparable的受限缺点的话,引入了Compartoe接口,compareTo方法只能写在该类中只能比较一个类属性,没有解决办法,所以我们引入了Compartor接口。

        

        这时就比较灵活,能够通过age或者grade随便排序和比较。

        

        

       这样就比较灵活了。


        3.2 Array.sort方法

        

        Arrays.sort(s, ageComparator) 的原理是基于快速排序或归并排序等高效的排序算法,并结合传入的 Comparator 对象 ageComparator 来确定元素的顺序。

        在排序过程中,每次需要比较两个元素时,都会调用 ageComparator 的 compare 方法来确定它们的相对顺序。compare 方法返回一个整数值,根据这个值来决定两个元素在排序后的数组中的位置。

        具体的排序算法会根据数组的大小和初始状态选择最优的策略,以尽可能高效地对数组进行排序。

        如果没有传入 Comparator 对象(即 Arrays.sort(s) ),并且数组元素的类型实现了 Comparable 接口,那么会使用元素自身的 compareTo 方法来进行比较和排序。

        上面的已经有演示了,我再演示一下Arrays.sort(s)这个。

        

       

3.3  优点:

        1.        灵活性:可以为同一个类提供多种不同的比较策略,根据不同的需求在不同的场景中使用不同的 Comparator 实现。

        2.        解耦:比较逻辑与被比较的类分离,使得类的设计更加专注于自身的核心功能,而比较逻辑可以在外部独立定义。

        3.        动态性:可以在运行时根据具体的条件创建和使用不同的 Comparator ,具有更强的动态性。

3.4 缺点

        1.        代码复杂:需要额外创建 Comparator 类,增加了代码量和复杂性。


3.5  二者的一些主要区别

       1. 实现的位置:          

  • Comparable 是在要进行比较的类内部实现比较逻辑。
  • Comparator 则是在类的外部单独定义比较规则。

        2.灵活性

  • Comparable 为类定义了一种固定的、自然的排序方式。
  • Comparator 更加灵活,可以根据不同的需求为同一个类定义多种不同的比较方式。

        3.代码结构

  • 使用 Comparable 时,比较逻辑与类的其他功能紧密结合。
  • 使用 Comparator 时,比较逻辑相对独立,代码结构更清晰。

        4.类的修改

  • 更改 Comparable 的比较逻辑需要修改类的代码。
  • Comparator 的修改不会影响到被比较的类本身。

        5.适用场景

  • 如果类本身具有明确且唯一的自然排序方式,适合使用 Comparable 。
  • 当需要在不同场景下对类进行不同方式的排序,或者类本身不适合修改来实现比较逻辑时,适合使用 Comparator 。

        6.集合排序

  • 对于实现了 Comparable 的类的对象数组,可直接使用 Arrays.sort 进行排序。
  • 对于未实现 Comparable 的类的对象数组,若要排序则必须提供 Comparator 对象给 Arrays.sort 。


四.结束语

         感谢大家的查看,希望可以帮助到大家,做的不是太好还请见谅,其中有什么不懂的可以留言询问,我都会一一回答。  感谢大家的一键三连。

  • 59
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值