Java数据结构_一篇文章搞定java对象的比较_7

news/2025/2/23 22:59:46

1. PriorityQueue中插入对象

上篇文章研究了优先级队列,优先级队列在插入元素中,要求插入的元素不能是null或者元素之间必须要能够进行比较,为了简单起见,上篇文章只是插入了Integer类型,那优先级队列中是否能插入自定义类型的对象呢

有如下代码:

class Card {
    private int rank; //数值
    private String suit; //花色

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

public class Test {
    public static void TestForPriority() {
        PriorityQueue<Card> p = new PriorityQueue<>();

        p.offer(new Card(1, "♥"));
        p.offer(new Card(2, "♥"));
    }

    public static void main(String[] args) {
        TestForPriority();
    }
}

运行结果为:

原因在上篇文中也有所提及,优先级队列底层使用堆,而向堆中插入元素中,为了满足堆的性质(offer方法中会检测是否有比较器,如果没有比较器会强转为Compareable),必须要进行元素的比较,而此时自定义类型Card是没有办法直接进行比较的,所以会抛出上面的异常。

2. 元素的比较

2.1 基本类型的比较

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

public class TestCompare {
    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.2 对象比较的问题

代码如下

如果在main方法中

有System.out.println(c1 > c2),会编译报错

有System.out.println(c1 == c2) 编译成功 --> 打印false 因为c1和c2指向不是同一个对象

有System.out.println(c1 < c2) 会编译报错

有System.out.println(c1 == c3) 编译成功 --> 打印true 因为c1 和 c3指向的是同一个对象

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

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

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

3. 对象的比较

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

3.1 覆写基类的equals方法

如图:在自定义类中重写equals方法

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

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

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

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

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

5. 注意下调用其他引用类型的比较也需要 equals,例如这里的 suit 的比较

重写equals方法虽然可以进行比较,但缺点是:equal方法的返回值是boolean类型,只能按照相等的比较,不能按照大于,小于的方式进行比较

3.2 基于Comparable接口类的比较

Comparable是JDK提供的泛型的比较接口类,源码实现为:

public interface Comparable<E> {

        //返回值:

        // < 0:表示this指向的对象小于 o 指向的对象

        // > 0:表示this指向的对象大于 o 指向的对象

        // == 0: 表示this指向的对象等于 o 指向的对象

        int compareTo(E o);

}

对于用户自定义类型,如果要按照自己的方式进行比较时: 在定义类的时候,实现Comparable接口,然后在类中重写compareTo方法即可

如下图:根据数值进行比较,不管花色,这里认为null是最小的

测试符合预期:

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

3.3 基于比较器比较

具体实现步骤如下:

1. 用户自定义比较器类,实现Comparator接口

public interface Comparator<T> {

        // 返回值: // < 0: 表示 o1 指向的对象小于 o2 指向的对象

        // == 0: 表示 o1 指向的对象等于 o2 指向的对象

        // > 0: 表示 o1 指向的对象等于 o2 指向的对象

        int compare(T o1, T o2);

}

注意区分Comparable  和 Comparator

2.覆写Comparator中的compare方法

测试符合预期:

注意:Comparator是java.util包中的泛型接口类, 使用时必须导入对应的包。

3.4 三种方式的对比

补充解释第二和第三种比较方式:

2. Comparable.comparaTo:

例如代码:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class Employee implements Comparable<Employee> {
    private String name;
    private int age;

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

    @Override
    public int compareTo(Employee other) {
        return Integer.compare(this.age, other.age);
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Employee{name='" + name + "', age=" + age + "}";
    }
}

public class Main {
    public static void main(String[] args) {
        List<Employee> employees = new ArrayList<>();
        employees.add(new Employee("Alice", 25));
        employees.add(new Employee("Bob", 20));
        employees.add(new Employee("Charlie", 30));

        // 对员工列表进行排序
        Collections.sort(employees);

        for (Employee employee : employees) {
            System.out.println(employee);
        }
    }
}

2. Comparator.compare

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        students.add(new Student("Alice", 20));
        students.add(new Student("Bob", 18));
        students.add(new Student("Charlie", 22));

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

        // 在排序算法中显式指定比较器
        Collections.sort(students, ageComparator);

        for (Student student : students) {
            System.out.println(student.getName() + " - " + student.getAge());
        }
    }
}

完!


http://www.niftyadmin.cn/n/5863846.html

相关文章

机器学习面试八股文——决战金三银四

大家好&#xff0c;这里是好评笔记&#xff0c;公主 号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本笔记的任务是解读机器学习实践/面试过程中可能会用到的知识点&#xff0c;内容通俗易懂&#xff0c;入门、实习和校招轻松搞定。 公主号合集地址 点击进入优惠地…

2025tg最新免费社工库机器人

情报局社工库 https://t.me/QingBaoJuXuanwubot?startNzExOTA0NzA2NA 小孩哥社工库 http://t.me/xiaohaigeSGK1_bot?startWGGVVrMgQiBslNE 冰墩墩个户机器人 t.me/bingdundung… 维基百科社工库 https://t.me/WikiSGKBot?start0b9d27c2e91b AI社工库 t.me/AI_SGKBOT?…

rpc到自己java实现rpc调用再到rpc框架设计

目录 rpc(Remote Procedure Call)rpc一般架构为什么要引入rpc自己实现rpc调用1. 新建一个maven项目&#xff0c;加入hessian依赖2. 服务端3. Stub代理4. 客户端测试输出5. rpc程序分析附 请求参数和序列化程序 6. 总结 回顾RPCRPC 序列化协议RPC 网络协议注册中心的引入dubbo框…

网络运维学习笔记 017 HCIA-Datacom综合实验01

文章目录 综合实验1实验需求总部特性 分支8分支9 配置一、 基本配置&#xff08;IP二层VLAN链路聚合&#xff09;ACC_SWSW-S1SW-S2SW-Ser1SW-CoreSW8SW9DHCPISPGW 二、 单臂路由GW 三、 vlanifSW8SW9 四、 OSPFSW8SW9GW 五、 DHCPDHCPGW 六、 NAT缺省路由GW 七、 HTTPGW 综合实…

使用 Grafana 监控 Spring Boot 应用

随着软件开发领域的不断发展&#xff0c;监控和可观测性已成为确保系统可靠性和性能的关键实践。Grafana 是一个功能强大的开源工具&#xff0c;能够为来自各种来源的监控数据提供丰富的可视化功能。在本篇博客中&#xff0c;我们将探讨如何将 Grafana 与 Spring Boot 应用程序…

LeetCode 热题 100 73. 矩阵置零

LeetCode 热题 100 | 73. 矩阵置零 大家好&#xff0c;今天我们来解决一道经典的算法题——矩阵置零。这道题在LeetCode上被标记为中等难度&#xff0c;要求我们将矩阵中为0的元素所在的行和列全部置为0。下面我将分别给出非原地算法和原地算法的Python代码实现&#xff0c;并…

共筑金融数字化新生态!YashanDB与恒生电子完成兼容互认证

近日&#xff0c;深圳计算科学研究院的崖山数据库系统YashanDB与恒生电子股份有限公司HUNDSUN资产估值与会计核算软件V6.0成功完成了兼容性互认证。结果显示&#xff0c;双方产品完全兼容&#xff0c;稳定运行&#xff0c;可共同为银行、证券、基金、保险、信托等金融机构提供稳…

21.《SpringBoot 异步编程@Async与CompletableFuture》

SpringBoot 异步编程 文章导读 本文系统讲解 Spring Boot 异步编程的核心技术与实践方案&#xff0c;涵盖从基础使用到高级优化的全链路知识。通过深入剖析 Async 注解原理、线程池配置策略、异步异常处理机制等关键技术点&#xff0c;结合典型业务场景的代码示例&#xff0c…