java对象对比之comparable和comparator的区别

 更新时间:2021年06月22日 11:36:13   作者:超分辨菜鸟  
今天给大家带来的是关于Java的相关知识,文章围绕着comparable和comparator的区别展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下

一、元素的比较

1.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);
    }

在这里插入图片描述

1.2 对象的比较

public class Main{
    public static void main(String[] args){
       Card c1 = new Card(1,"♠");
        Card c2 = new Card(2,"♠");
        Card c3 = c1;
        System.out.println(c1==c2);
        System.out.println(c1==c3);
//        System.out.println(c1>c2);  编译报错
//        System.out.println(c1<c2);  编译报错
    }

}
class  Card{
    public int rank;
    public String suit;
     public Card(int rank,String suit){
         this.rank = rank;
         this.suit = suit;
     }
}

在这里插入图片描述

可以看出在进行相等比较时,是可以进行比较的,但进行大于或小于比较就不行了
这是因为对于用户实现自定义类型,都默认继承自Object类,而Object类中提供了equal方法,而==默认情况下调用的就是equal方法,但是该方法的比较规则是:没有比较引用变量引用对象的内容,而是直接比较引用变量的地址,但有些情况下该种比较就不符合题意。

二、对象的比较

有些情况下,需要比较的是对象中的内容,比如:向优先级队列中插入某个对象时,需要对按照对象中内容来调整堆,那该如何处理呢?

2.1 覆写基类的equal

在这里插入图片描述

一般覆写 equals 的套路就是上面演示的

1.如果指向同一个对象,返回 true

2.如果传入的为 null,返回 false

3.如果传入的对象类型不是 Card,返回 false

4.按照类的实现目标完成比较,例如这里只要花色和数值一样,就认为是相同的牌

5.注意下调用其他引用类型的比较也需要 equals,例如这里的 suit 的比较
覆写基类equal的方式虽然可以比较,但缺陷是:equal只能按照相等进行比较,不能按照大于、小于的方式进行比较。

2.2 基于Comparable接口的比较

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

public interface Comparable<T> {
    /**
     * Compares this object with the specified object for order.  Returns a
     * negative integer, zero, or a positive integer as this object is less
     * than, equal to, or greater than the specified object.
     *
     * <p>The implementor must ensure <tt>sgn(x.compareTo(y)) ==
     * -sgn(y.compareTo(x))</tt> for all <tt>x</tt> and <tt>y</tt>.  (This
     * implies that <tt>x.compareTo(y)</tt> must throw an exception iff
     * <tt>y.compareTo(x)</tt> throws an exception.)
     *
     * <p>The implementor must also ensure that the relation is transitive:
     * <tt>(x.compareTo(y)&gt;0 &amp;&amp; y.compareTo(z)&gt;0)</tt> implies
     * <tt>x.compareTo(z)&gt;0</tt>.
     *
     * <p>Finally, the implementor must ensure that <tt>x.compareTo(y)==0</tt>
     * implies that <tt>sgn(x.compareTo(z)) == sgn(y.compareTo(z))</tt>, for
     * all <tt>z</tt>.
     *
     * <p>It is strongly recommended, but <i>not</i> strictly required that
     * <tt>(x.compareTo(y)==0) == (x.equals(y))</tt>.  Generally speaking, any
     * class that implements the <tt>Comparable</tt> interface and violates
     * this condition should clearly indicate this fact.  The recommended
     * language is "Note: this class has a natural ordering that is
     * inconsistent with equals."
     *
     * <p>In the foregoing description, the notation
     * <tt>sgn(</tt><i>expression</i><tt>)</tt> designates the mathematical
     * <i>signum</i> function, which is defined to return one of <tt>-1</tt>,
     * <tt>0</tt>, or <tt>1</tt> according to whether the value of
     * <i>expression</i> is negative, zero or positive.
     *
     * @param   o the object to be compared.
     * @return  a negative integer, zero, or a positive integer as this object
     *          is less than, equal to, or greater than the specified object.
     *
     * @throws NullPointerException if the specified object is null
     * @throws ClassCastException if the specified object's type prevents it
     *         from being compared to this object.
     */
    public int compareTo(T o);
}

可以看到在Comparable接口中只实现了一个方法 compareTo,因此我们在实现自定义比较时,在类的定义中实现Comparable接口即可,然后在类中重写compareTo方法

public class Main{
    public static void main(String[] args){
        Card c1 = new Card(1,"♠");
        Card c2 = new Card(2,"♠");
        Card c3 = c1;
        System.out.println(c1.compareTo(c2));
        System.out.println(c1.compareTo(c3));
        System.out.println(c2.compareTo(c3));
        
    }

}
class  Card implements Comparable<Card>{
    public int rank;
    public String suit;
     public Card(int rank,String suit){
         this.rank = rank;
         this.suit = suit;
     }

    @Override
    public int compareTo(Card o) {
        if(o==null){
            return 1;
        }
        return rank-o.rank;
    }
}

在这里插入图片描述

当前值比要比较值小则输出-1;当前值与要比较值相等则输出0;
当前值比要比较值大输出1;

2.3 基于比较器Comparator的比较

首先了解一下Comparator接口

public interface Comparator<T> {
    /**
     * Compares its two arguments for order.  Returns a negative integer,
     * zero, or a positive integer as the first argument is less than, equal
     * to, or greater than the second.<p>
     *
     * In the foregoing description, the notation
     * <tt>sgn(</tt><i>expression</i><tt>)</tt> designates the mathematical
     * <i>signum</i> function, which is defined to return one of <tt>-1</tt>,
     * <tt>0</tt>, or <tt>1</tt> according to whether the value of
     * <i>expression</i> is negative, zero or positive.<p>
     *
     * The implementor must ensure that <tt>sgn(compare(x, y)) ==
     * -sgn(compare(y, x))</tt> for all <tt>x</tt> and <tt>y</tt>.  (This
     * implies that <tt>compare(x, y)</tt> must throw an exception if and only
     * if <tt>compare(y, x)</tt> throws an exception.)<p>
     *
     * The implementor must also ensure that the relation is transitive:
     * <tt>((compare(x, y)&gt;0) &amp;&amp; (compare(y, z)&gt;0))</tt> implies
     * <tt>compare(x, z)&gt;0</tt>.<p>
     *
     * Finally, the implementor must ensure that <tt>compare(x, y)==0</tt>
     * implies that <tt>sgn(compare(x, z))==sgn(compare(y, z))</tt> for all
     * <tt>z</tt>.<p>
     *
     * It is generally the case, but <i>not</i> strictly required that
     * <tt>(compare(x, y)==0) == (x.equals(y))</tt>.  Generally speaking,
     * any comparator that violates this condition should clearly indicate
     * this fact.  The recommended language is "Note: this comparator
     * imposes orderings that are inconsistent with equals."
     *
     * @param o1 the first object to be compared.
     * @param o2 the second object to be compared.
     * @return a negative integer, zero, or a positive integer as the
     *         first argument is less than, equal to, or greater than the
     *         second.
     * @throws NullPointerException if an argument is null and this
     *         comparator does not permit null arguments
     * @throws ClassCastException if the arguments' types prevent them from
     *         being compared by this comparator.
     */
    int compare(T o1, T o2);

当然还有许多comparator实现的自定义比较方法,但这里我只贴出需要自己实现的方法compare;
接下来看看comparator的用法
当使用comparator时,如果要使用自定义的比较方式需要实现comparator接口,并且覆写compare方法;因此需要自己构造一个比较器类实现comparator接口,然后利用我们自定义的比较器进行比较即可;
下面是一个应用实例

// write your code here
import java.util.*;
import java.lang.*;

public class Main{
    public static void main(String[] args){
        Card c1 = new Card(1,"♠");
        Card c2 = new Card(2,"♠");
        Card c3 = c1;
        CardComparator cardComparator = new CardComparator();
        System.out.println(cardComparator.compare(c1,c2));
        System.out.println(cardComparator.compare(c1,c3));
        System.out.println(cardComparator.compare(c2,c3));
    }
}
class  Card {
    public int rank;
    public String suit;
     public Card(int rank,String suit){
         this.rank = rank;
         this.suit = suit;
     }
}
class  CardComparator implements Comparator<Card>{

    @Override
    public int compare(Card o1, Card o2) {
        if (o1==o2){
            return 0;
        }
        if (o1==null)return -1;
        if (o2==null)return 1;
        return o1.rank-o2.rank;
    }
}

在这里插入图片描述

Comparator属于java.util包中泛型接口类,使用时必须导入相关的包;
我们将Comparator中的compare方法重写,就可以对需要进行对比的对象进行对比并返回结果。

2.4 几种不同的compare对比

方法 说明
object.equals 直接覆写即可,不过只能比较相等与否
Comparable.compareTO 需要手动实现接口,当前类之后的所有对比方式都被定义,属于内部顺序
Comparator.compare 需要实现一个比较器对象,对待比较类的侵入性弱,但对代码的侵入性强

到此这篇关于java对象对比之comparable和comparator的区别的文章就介绍到这了,更多相关comparable和comparator的区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Boot和Vue前后端分离项目架构的全过程

    Spring Boot和Vue前后端分离项目架构的全过程

    前后端分离是目前互联网开发中比较广泛使用的开发模式,主要是将前端和后端的项目业务进行分离,下面这篇文章主要给大家介绍了关于Spring Boot和Vue前后端分离项目架构的相关资料,需要的朋友可以参考下
    2022-04-04
  • java对象转化成String类型的四种方法小结

    java对象转化成String类型的四种方法小结

    在java项目的实际开发和应用中,常常需要用到将对象转为String这一基本功能。本文就详细的介绍几种方法,感兴趣的可以了解一下
    2021-08-08
  • MyBatis-Plus 使用枚举自动关联注入

    MyBatis-Plus 使用枚举自动关联注入

    本文主要介绍了MyBatis-Plus 使用枚举自动关联注入,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-06-06
  • 浅谈spring aop的五种通知类型

    浅谈spring aop的五种通知类型

    这篇文章主要介绍了浅谈spring aop的五种通知类型,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • Java IO流之字符缓冲流实例详解

    Java IO流之字符缓冲流实例详解

    这篇文章主要介绍了Java IO流之字符缓冲流,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-05-05
  • Java利用SpEL表达式实现权限校验

    Java利用SpEL表达式实现权限校验

    这篇文章主要为大家详细介绍了Java如何利用SpEL表达式实现权限校验功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-01-01
  • spring security认证异常后返回中文提示的问题

    spring security认证异常后返回中文提示的问题

    这篇文章主要介绍了spring security认证异常后返回中文提示的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • SpringBoot+WebSocket向前端推送消息的实现示例

    SpringBoot+WebSocket向前端推送消息的实现示例

    WebSocket是一种在单个TCP连接上进行全双工通信的协议,允许服务器主动向客户端推送信息,同时也能从客户端接收信息,本文主要介绍了SpringBoot+WebSocket向前端推送消息的实现示例,感兴趣的可以了解一下
    2024-08-08
  • springboot配置mysql数据库spring.datasource.url报错的解决

    springboot配置mysql数据库spring.datasource.url报错的解决

    这篇文章主要介绍了springboot配置mysql数据库spring.datasource.url报错的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • javacv开发详解之调用本机摄像头视频

    javacv开发详解之调用本机摄像头视频

    这篇文章主要介绍了javacv开发详解之调用本机摄像头视频,对javacv感兴趣的同学,可以参考下
    2021-04-04

最新评论