Java基础(十二)Java比较器

news2024/11/24 9:28:47

1 Java 比较器

我们知道基本数据类型的数据(除boolean类型外)需要比较大小的话,直接使用比较运算符即可,但是引用数据类型是不能直接使用比较运算符来比较大小的。那么,如何解决这个问题呢?
请添加图片描述

  • 在Java中经常会涉及到对象数组的排序问题,那么就涉及到对象之间的比较问题。

  • Java实现对象排序的方式有两种:

    • 自然排序:java.lang.Comparable
    • 定制排序:java.util.Comparator

1.1 自然排序:java.lang.Comparable

  • Comparable接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序。
  • 实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即通过 compareTo(Object obj) 方法的返回值来比较大小。如果当前对象this大于形参对象obj,则返回正整数,如果当前对象this小于形参对象obj,则返回负整数,如果当前对象this等于形参对象obj,则返回零。
package java.lang;

public interface Comparable{
    int compareTo(Object obj);
}
  • 实现Comparable接口的对象列表(和数组)可以通过 Collections.sort 或 Arrays.sort进行自动排序。实现此接口的对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。

  • 对于类 C 的每一个 e1 和 e2 来说,当且仅当 e1.compareTo(e2) == 0 与 e1.equals(e2) 具有相同的 boolean 值时,类 C 的自然排序才叫做与 equals 一致。建议(虽然不是必需的)最好使自然排序与 equals 一致

  • Comparable 的典型实现:(默认都是从小到大排列的)

    • String:按照字符串中字符的Unicode值进行比较
    • Character:按照字符的Unicode值来进行比较
    • 数值类型对应的包装类以及BigInteger、BigDecimal:按照它们对应的数值大小进行比较
    • Boolean:true 对应的包装类实例大于 false 对应的包装类实例
    • Date、Time等:后面的日期时间比前面的日期时间大
  • 代码示例:


public class Student implements Comparable {
    private int id;
    private String name;
    private int score;
    private int age;

    public Student(int id, String name, int score, int age) {
        this.id = id;
        this.name = name;
        this.score = score;
        this.age = age;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", score=" + score +
                ", age=" + age +
                '}';
    }

    @Override
    public int compareTo(Object o) {
        //这些需要强制,将o对象向下转型为Student类型的变量,才能调用Student类中的属性
        //默认按照学号比较大小
        Student stu = (Student) o;
        return this.id - stu.id;
    }
}

测试类


public class TestStudent {
    public static void main(String[] args) {
        Student[] arr = new Student[5];
        arr[0] = new Student(3,"张三",90,23);
        arr[1] = new Student(1,"熊大",100,22);
        arr[2] = new Student(5,"王五",75,25);
        arr[3] = new Student(4,"李四",85,24);
        arr[4] = new Student(2,"熊二",85,18);

        //单独比较两个对象
        System.out.println(arr[0].compareTo(arr[1]));
        System.out.println(arr[1].compareTo(arr[2]));
        System.out.println(arr[2].compareTo(arr[2]));

        System.out.println("所有学生:");
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
        System.out.println("按照学号排序:");
        for (int i = 1; i < arr.length; i++) {
            for (int j = 0; j < arr.length-i; j++) {
                if(arr[j].compareTo(arr[j+1])>0){
                    Student temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

再举例:

public class Student implements Comparable {
    private String name;
    private int score;

    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", score=" + score +
                '}';
    }

    @Override
    public int compareTo(Object o) {
        return this.score - ((Student)o).score;
    }
}

测试:

@Test
public void test02() {
	Student[] students = new Student[3];
	students[0] = new Student("张三", 96);
	students[1] = new Student("李四", 85);
	students[2] = new Student("王五", 98);

	System.out.println(Arrays.toString(students));
	Arrays.sort(students);
	System.out.println(Arrays.toString(students));
}

再举例:

class Goods implements Comparable {
    private String name;
    private double price;

    //按照价格,比较商品的大小
    @Override
    public int compareTo(Object o) {
        if(o instanceof Goods) {
            Goods other = (Goods) o;
            if (this.price > other.price) {
                return 1;
            } else if (this.price < other.price) {
                return -1;
            }
            return 0;
        }
        throw new RuntimeException("输入的数据类型不一致");
    }
    //构造器、getter、setter、toString()方法略
}


测试:

public class ComparableTest{
    public static void main(String[] args) {

        Goods[] all = new Goods[4];
        all[0] = new Goods("《红楼梦》", 100);
        all[1] = new Goods("《西游记》", 80);
        all[2] = new Goods("《三国演义》", 140);
        all[3] = new Goods("《水浒传》", 120);

        Arrays.sort(all);

        System.out.println(Arrays.toString(all));

    }

}

1.2 定制排序:java.util.Comparator

  • 思考
    • 当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码(例如:一些第三方的类,你只有.class文件,没有源文件)
    • 如果一个类,实现了Comparable接口,也指定了两个对象的比较大小的规则,但是此时此刻我不想按照它预定义的方法比较大小,但是我又不能随意修改,因为会影响其他地方的使用,怎么办?
  • JDK在设计类库之初,也考虑到这种情况,所以又增加了一个java.util.Comparator接口。强行对多个对象进行整体排序的比较。
    • 重写compare(Object o1,Object o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。
    • 可以将 Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort),从而允许在排序顺序上实现精确控制。
package java.util;

public interface Comparator{
    int compare(Object o1,Object o2);
}

举例:


import java.util.Comparator;
//定义定制比较器类
public class StudentScoreComparator implements Comparator { 
    @Override
    public int compare(Object o1, Object o2) {
        Student s1 = (Student) o1;
        Student s2 = (Student) o2;
        int result = s1.getScore() - s2.getScore();
        return result != 0 ? result : s1.getId() - s2.getId();
    }
}

测试类


public class TestStudent {
    public static void main(String[] args) {
        Student[] arr = new Student[5];
        arr[0] = new Student(3, "张三", 90, 23);
        arr[1] = new Student(1, "熊大", 100, 22);
        arr[2] = new Student(5, "王五", 75, 25);
        arr[3] = new Student(4, "李四", 85, 24);
        arr[4] = new Student(2, "熊二", 85, 18);


        System.out.println("所有学生:");
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }

        System.out.println("按照成绩排序");
        StudentScoreComparator sc = new StudentScoreComparator();
        for (int i = 1; i < arr.length; i++) {
            for (int j = 0; j < arr.length - i; j++) {
                if (sc.compare(arr[j], arr[j + 1]) > 0) {
                    Student temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

再举例:

@Test
public void test01() {
    Student[] students = new Student[5];
    students[0] = new Student(3, "张三", 90, 23);
    students[1] = new Student(1, "熊大", 100, 22);
    students[2] = new Student(5, "王五", 75, 25);
    students[3] = new Student(4, "李四", 85, 24);
    students[4] = new Student(2, "熊二", 85, 18);

    System.out.println(Arrays.toString(students));
    //定制排序
    StudentScoreComparator sc = new StudentScoreComparator();
    Arrays.sort(students, sc);
    System.out.println("排序之后:");
    System.out.println(Arrays.toString(students));
}

再举例:

Goods[] all = new Goods[4];
all[0] = new Goods("War and Peace", 100);
all[1] = new Goods("Childhood", 80);
all[2] = new Goods("Scarlet and Black", 140);
all[3] = new Goods("Notre Dame de Paris", 120);

Arrays.sort(all, new Comparator() {

    @Override
    public int compare(Object o1, Object o2) {
        Goods g1 = (Goods) o1;
        Goods g2 = (Goods) o2;

        return g1.getName().compareTo(g2.getName());
    }
});

System.out.println(Arrays.toString(all));

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/457063.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Jomalone(“独狼”)的Rootkit后门dll分析

从England.sys&#xff08;md5为B5F7DE342B1D661E57BCD14615CADEFA&#xff09;驱动文件中提取了4个dll文件&#xff0c;其中两个64位dll&#xff0c;两个32位dll&#xff0c;主要用于APC注入 样本的基本信息 文件名称: 0x3df60-0x15e00.dll 文件大小: 87.5 KB (89,600 字节) …

Kubeadm方式搭建K8s集群【1.23.0版本】

文章目录 一、初始化准备二、安装kubeadm三、初始化Master集群四、将新的Node节点加入集群五、部署CNI网络插件六、其他配置 Kubernetes1.24(包括1.24)之后不在兼容docker,如果有需要兼容docker的需求&#xff0c;则安装一个 cri-docker的插件&#xff0c;本文使用的是kuberne…

【SWAT水文模型】ArcSWAT输入准备

ArcSWAT输入准备 1 必需的ArcSWAT空间数据集1.1 数字高程模型&#xff08;DEM&#xff09;1.2 土地覆盖/土地利用类型1.3 土壤数据 2 可选的ArcSWAT空间数据集2.1 DEM Mask2.2 Streams2.3 User- Defined Watersheds 3 ArcSWAT表格和文本文件3.1 子流域出口位置表(dBase 表)3.2 …

【MCAL_Uart】-1.1-图文详解Uart串口协议

目录 1 什么是UART 2 UART的电平 3 UART的波特率 4 UART帧格式 4.1 start bit起始位 4.2 data bit数据位 4.3 parity bit奇偶校验位 4.4 stop bit停止位 5 什么是8-N-1 6 UART总线负载率计算 结尾 优质博文推荐阅读&#xff08;单击下方链接&#xff0c;即可跳转&am…

shell脚本基础之详解脚本的控制

详解脚本的控制 信号的处理Linux信号生成信号中断进程暂停进程 捕获信号捕获脚本退出修改或移除捕获 以后台模式运行脚本后台运行脚本运行多个后台脚本 在非控制台下运行脚本作业控制 查看作业重启停止的作业调整谦让度nice命令renice命令 定时运行作业用 at 命令来定时执行作业…

2023移动云大会即将召开,划重点来了

今年由 ChatGPT 引起的AI浪潮下&#xff0c;人们热议其背后的算力问题&#xff0c;毋庸置疑&#xff0c;算力已成为和水电同样重要的资源。作为开发者&#xff0c;如何了解云计算领域有哪些最新发展趋势&#xff1f; 4月25-26日&#xff0c;以“云擎未来&#xff0c;智信天下”…

Scala之集合(3)

目录 WordCount案例&#xff1a; 需求分析与步骤&#xff1a; 拆分&#xff1a; 聚合&#xff1a; 格式转化&#xff1a; 方法1&#xff1a; 方法2&#xff1a; 排序&#xff1a; 方法1&#xff1a; 方法2&#xff1a; 取top3&#xff1a; 整体化简后的代码&#xf…

轻量级服务器nginx:配置虚拟主机的两种方式

虚拟主机是指&#xff0c;在一台服务器中&#xff0c;通过nginx的代理&#xff0c;我们可以访问多个网站。区分不同的网站&#xff0c;可以通过端口、域名两种方式 这里写目录标题 一 端口不同区分不同的虚拟主机二 通过域名区分不同的主机名1.配置域名映射2.显示登录效果 一 …

基于ATECLOUD电源模块及单板性能自动化测试方案

一、背景介绍 客户使用直流电源、交流电源、直流负载、示波器、数据记录仪、功率分析仪、CAN卡、工控机等仪器对电源模块及单板进行功能和性能方面的测试&#xff0c;目前想要能够通过硬件自动化测试分析系统搭配对应仪器实现自动化测试&#xff0c;提升测试效率。 二、用户痛…

Linux网络——NFS共享服务

Linux网络——NFS共享服务 一、NFS共享服务1.NFS网络文件系统2.NFS 架构3.NFS 工作原理4.NFS相关配置文件及其配置作用 二、搭建NFS服务1.服务器安装 nfs-utils、rpcbind 软件包2.服务器启动nfs-utils、rpcbind服务&#xff0c;并设置共享目录3.服务端更改NFS配置&#xff0c;对…

scrapy实践-02

双师demo ptpress.com.cn/shopping/index 解析每一首歌 <ul class"f-hide"><li><a href"/song?id2037945324">芯房</a></li><li><a href"/song?id2037926385">知足</a></li><li>…

QMS-云质说质量 - 3 来料检验的九大坑,你踩过几个?

大家好&#xff0c;今天我们来讲一讲来料检验。 先重点强调一下&#xff0c;我们讨论的范围是采购大量零部件的离散制造企业&#xff0c;而不是全部类型的企业。 负责来料检验的是IQC部门。相对于整个公司的组织架构来说&#xff0c;IQC是一个很小、很小的部门。负责的事情也很…

2023找工作,怎么样才能成功跳槽面试拿到高薪呢?

前言 无论是在校招还是社会企业招聘中&#xff0c;应聘者总是要经过层层的考核才能被聘用。然而&#xff0c;在招聘时&#xff0c;设置的编程以及非技术面试问题&#xff0c;真的有必要吗&#xff1f;如此就能考核出一位开发者的真实水平&#xff1f; 说到底就是考验你的技术以…

WSL2 对外暴露端口

参考文档 一口气搞定 WSL2 的网络问题从局域网 (LAN) 访问 WSL 2 发行版通过本地网络连接到 WSL2 服务器 按照下面的操作步骤进行操作。 1. powershell 支持 sudo https://github.com/gerardog/gsudo 可以直接下载msi安装&#xff1a;https://github.com/gerardog/gsudo/rel…

excel数据分析比赛

基础 sql:百度网盘 请输入提取码 excel函数 <

Git+SpringBoot详谈

&#x1f648;作者简介&#xff1a;练习时长两年半的Java up主 &#x1f649;个人主页&#xff1a;老茶icon &#x1f64a; ps:点赞&#x1f44d;是免费的&#xff0c;却可以让写博客的作者开兴好久好久&#x1f60e; &#x1f4da;系列专栏&#xff1a;Java全栈&#xff0c;计…

Linux:shell+权限

索引 1.shell命令及其理解2.Linux权限及其理解1.权限基本概念2.修改权限3.权限掩码umask4.修改拥有者和所属组 3.粘滞位 1.shell命令及其理解 定义&#xff1a;命令行解释器 作用&#xff1a; 将使用者的命令翻译给kernal&#xff08;核心&#xff09;处理将核心的处理结果返…

隧道工程运维VR虚拟实操模拟训练提高学生动手能力

轨道交通作为我国国民经济的命脉和交通运输的骨干网络&#xff0c;不仅承担了绝大部分国家战略、经济物资的运输&#xff0c;还承担着客运运输职能。随着政策的重视和专业的细分&#xff0c;轨道交通的人才需求越来越大&#xff0c;但是目前传统教学面临着一些问题。 • 轨道交…

【AutoGPT】AutoGPT出现,是否意味着ChatGPT已被淘汰

Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员&#xff0c;2024届电子信息研究生 目录 前言 什么是ChatGPT&#xff1f; 什么是AutoGPT&#xff1f; AutoGPT与ChatGPT的区别 AutoGPT的优势和劣势 优势 劣势 ChatGPT是否会被淘汰&#xff1f; 前言 近年来&#x…

软件测试技术那么多,我们该如何分辨?

经典软件测试技术分类&#xff1a; 测试技术是指顺利完成测试的一系列相关过程&#xff0c;有很多可能的分类方式&#xff0c;表2-1就是其中的一种。表中列出了流行的测试技术&#xff0c;也按照上面的讨论对其进行分类&#xff1a;手工测试、自动测试、静态测试、动态测试、功…