java对象的比较

简介: java对象的比较

上一章中关于PriorityQueue的使用要注意:


1. PriorityQueue中放置的元素必须要能够比较大小,不能插入无法比较大小的对象,否则会抛出

ClassCastException异常

2. 不能插入null对象,否则会抛出NullPointerException

3. 没有容量限制,可以插入任意多个元素,其内部可以自动扩容

4. 插入和删除元素的时间复杂度为

5. PriorityQueue底层使用了堆数据结构

6. PriorityQueue默认情况下是小堆---即每次获取到的元素都是最小的元素

优先级队列在插入元素时有个要求:插入的元素不能是null或者元素之间必须要能够进行比较,比如Integer,那优先级队列中能否插入自定义类型对象呢?


这里就会涉及到元素之间的比较。


1. 元素比较


对于元素,我们分为两大类,一类为基本数据类型,另一类为引用类型。


基本数据类型很好比较,整型,浮点型,布尔型都可以比较其大小。


那么引用类型如何比较呢?


比如两个人,两栋楼?


例如:


我们创建一个扑克牌类:


class Card {
    public int rank; // 数值
    public String suit; // 花色
    public Card(int rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }
}

26ddfbbfbb9d45a28924674d487ef43c.png


从编译结果可以看出,Java中引用类型的变量不能直接按照 > 或者 < 方式进行比较。 那为什么==可以比较?


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


Object中equal的实现,可以看到:直接比较的是两个引用变量的地址:


93c970bd01764c1cba1192bc82a3770e.png


2. 对象的比较


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

我们一共有三种方法来实现:重写equals()方法 、 Comparble接口 、 比较器


2.1 重写equals


这是最好理解的一种比较方法。


例如:


46a141cb31074ce6b3d22c30cf003a9b.png



注意基本类型可以直接比较,但引用类型最好调用其equal方法。

虽然重写equals方法很好用,但是却有个致命缺陷,它只能比较是否相等,但是却不能比较大小。

2.2 Comparble接口类的比较

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



f9ba1d1fa87f471780d6bbcf64c57565.png


Comparable接口中只提供了compareTo方法,  

返回值如下图:


8e4f6fe971bd42bc9d312fbf8c4e76e1.png


我们还是以上面的扑克为例:


1729bb39968840c599f70a270beee9c1.png

来看看实际效果:

c3d4bf613fa74fd391518becfcce82a3.png

2.3 比较器

Comparator 的简介:


Comparator 是比较器接口。


我们若需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口);那么,我们可以建立一个“该类的比较器”来进行排序。这个“比较器”只需要实现Comparator接口即可。也就是说,我们可以通过“实现Comparator类来新建一个比较器”,然后通过该比较器对类进行排序。

Comparator 的定义:

Comparator 接口仅仅只包括两个函数,它的定义如下:

int compare(T o1, T o2);
boolean equals(Object obj);




说明:

若一个类要实现Comparator接口:它一定要实现compareTo(T o1, T o2) 函数,但可以不实现 equals(Object obj) 函数。

为什么可以不实现 equals(Object obj) 函数呢? 因为任何类,默认都是已经实现了equals(Object obj)的。 Java中的一切类都是继承于java.lang.Object,在Object.java中实现了equals(Object obj)函数;所以,其它所有的类也相当于都实现了该函数。

int compare(T o1, T o2) 是“比较o1和o2的大小”。返回“负数”,意味着“o1比o2小”;返回“零”,意味着“o1等于o2”;返回“正数”,意味着“o1大于o2”。


我们来依旧使用上面的例子:


ffa208faafaa4892b094b664afe94399.png

结构如下:

7baaf3209a45416088d00e1eeab8a220.png

三种方式的比较:


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


相关文章
|
1月前
|
存储 缓存 监控
Java面试题:在Java中,对象何时可以被垃圾回收?编程中,如何更好地做好垃圾回收处理?
Java面试题:在Java中,对象何时可以被垃圾回收?编程中,如何更好地做好垃圾回收处理?
34 0
|
5天前
|
缓存 前端开发 Java
【前端学java】复习巩固-Java中的对象比较(15)
【8月更文挑战第11天】Java中的对象比较
15 1
【前端学java】复习巩固-Java中的对象比较(15)
|
11天前
|
存储 Java 程序员
Java中对象几种类型的内存分配(JVM对象储存机制)
Java中对象几种类型的内存分配(JVM对象储存机制)
45 5
Java中对象几种类型的内存分配(JVM对象储存机制)
|
3天前
|
Java API 开发者
|
11天前
|
存储 Java 程序员
08 Java面向对象基础(对象与类+实例变量与方法+构造方法+this关键字)
08 Java面向对象基础(对象与类+实例变量与方法+构造方法+this关键字)
33 4
|
15天前
|
存储 安全 Java
揭秘Java序列化神器Serializable:一键解锁对象穿越时空的超能力,你的数据旅行不再受限,震撼登场!
【8月更文挑战第4天】Serializable是Java中的魔术钥匙,开启对象穿越时空的能力。作为序列化的核心,它让复杂对象的复制与传输变得简单。通过实现此接口,对象能被序列化成字节流,实现本地存储或网络传输,再通过反序列化恢复原状。尽管使用方便,但序列化过程耗时且存在安全风险,需谨慎使用。
27 7
|
2天前
|
存储 设计模式 Java
在 Java 中创建多个对象
【8月更文挑战第17天】
6 0
|
5天前
|
Java Spring 容器
Java SpringBoot 中,动态执行 bean 对象中的方法
Java SpringBoot 中,动态执行 bean 对象中的方法
14 0
|
5天前
|
Java
Java Bean 注册对象
Java Bean 注册对象
6 0
|
27天前
|
Java 运维
开发与运维技术问题之ava对象头压缩技术支持所有的Java垃圾回收器如何解决
开发与运维技术问题之ava对象头压缩技术支持所有的Java垃圾回收器如何解决
21 1