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 需要实现一个比较器对象,对待比较类的侵入性弱,但对算法代码实现侵入性


相关文章
|
18天前
|
安全 Java 编译器
Java对象一定分配在堆上吗?
本文探讨了Java对象的内存分配问题,重点介绍了JVM的逃逸分析技术及其优化策略。逃逸分析能判断对象是否会在作用域外被访问,从而决定对象是否需要分配到堆上。文章详细讲解了栈上分配、标量替换和同步消除三种优化策略,并通过示例代码说明了这些技术的应用场景。
Java对象一定分配在堆上吗?
|
22天前
|
Java API
Java 对象释放与 finalize 方法
关于 Java 对象释放的疑惑解答,以及 finalize 方法的相关知识。
42 17
|
21天前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第22天】在Java的世界里,对象序列化和反序列化是数据持久化和网络传输的关键技术。本文将带你了解如何在Java中实现对象的序列化与反序列化,并探讨其背后的原理。通过实际代码示例,我们将一步步展示如何将复杂数据结构转换为字节流,以及如何将这些字节流还原为Java对象。文章还将讨论在使用序列化时应注意的安全性问题,以确保你的应用程序既高效又安全。
|
30天前
|
存储 Java 数据管理
Java零基础-Java对象详解
【10月更文挑战第7天】Java零基础教学篇,手把手实践教学!
25 6
|
1月前
|
Oracle Java 关系型数据库
重新定义 Java 对象相等性
本文探讨了Java中的对象相等性问题,包括自反性、对称性、传递性和一致性等原则,并通过LaptopCharger类的例子展示了引用相等与内容相等的区别。文章还介绍了如何通过重写`equals`方法和使用`Comparator`接口来实现更复杂的相等度量,以满足特定的业务需求。
21 3
|
1月前
|
存储 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第9天】在Java的世界里,对象序列化是连接数据持久化与网络通信的桥梁。本文将深入探讨Java对象序列化的机制、实践方法及反序列化过程,通过代码示例揭示其背后的原理。从基础概念到高级应用,我们将一步步揭开序列化技术的神秘面纱,让读者能够掌握这一强大工具,以应对数据存储和传输的挑战。
|
1月前
|
XML Java Maven
在 Cucumber 测试中自动将 Cucumber 数据表映射到 Java 对象
在 Cucumber 测试中自动将 Cucumber 数据表映射到 Java 对象
53 7
|
1月前
|
存储 Java 数据管理
Java零基础-Java对象详解
【10月更文挑战第3天】Java零基础教学篇,手把手实践教学!
16 1
|
2月前
|
Java
java基础(12)抽象类以及抽象方法abstract以及ArrayList对象使用
本文介绍了Java中抽象类和抽象方法的使用,以及ArrayList的基本操作,包括添加、获取、删除元素和判断列表是否为空。
27 2
java基础(12)抽象类以及抽象方法abstract以及ArrayList对象使用
|
1月前
|
Java 数据安全/隐私保护
java类和对象
java类和对象
25 5