深入理解Java比较器(Comparable和Comparator)

2023-10-27

深入理解Java比较器(Comparable和Comparator)


在java中经常涉及到 对象数组的比较的情况,常见的有两种方法来处理:

  1. 继承comparable接口,并实现compareTo()方法
  2. 定义一个单独的对象比较器,继承自Comparator接口,实现compare()方法

一、 Comparable

若一个类实现了Comparable接口,就意味着该类支持排序。实现了 Comparable接口的类的对象的列表或数组可以通过Collections.sort或Arrays.sort进行自动排序。
此外,实现此接口的对象可以用作有序映射中的键或有序集合中的集合,无需指定比较器
此接口只有一个方法compare,比较此对象与指定对象的顺序,如果该对象小于、等于或大于指定 对象,则分别返回负整数、零或正整数。

1、Comparable 接口定义

Comparable 接口仅仅只包括一个函数,如下

package java.lang;
import java.util.*;

public interface Comparable {
    //必须实现的抽象方法
    public int compareTo(T o);
}

说明:根据这个方法的返回值来判断

大于0:说明前一个比后一个大

小于0:说明前一个小于后一个

等于0:说明这两个一样大

示例:

这里有一个员工类Employee1,我们需要堆员工实体对员工的工资进行排序,所以这里用实现Comparable接口,重写compareTo方法

import java.util.Arrays;

public class Employee1 implements Comparable<Employee1>{

    private String name;
    private double salary;

    public Employee1(String name , double salary){
        this.name = name;
        this.salary = salary;
    }

    public Employee1(String name , double salary, int height){
        this.name = name;
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

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

    public Double getSalary() {
        return salary;
    }

    public void setSalary(Double salary) {
        this.salary = salary;
    }

    public void raiseSalary(double byPercent) {
        double raise = salary * byPercent / 100;
        salary += raise;
    }

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

    /**
     * 重写排序规则:
     * 定义我们的排序规则,用salary来排序
     * @param other
     * @return
     */
    @Override
    public int compareTo(Employee1 other) {
        return Double.compare(salary,other.salary);
    }
}

此时:我们重写了compareTo方法,可以看出是用成员变量salary进行了比较,当前一个对象小于后一个对象时,返回小于0,反之大于0,等于则返回0.

测试类:

	public static void main(String[] args) {
        Employee1[] temp=new Employee1[4];
        temp[0]=new Employee1("张三",150);
        temp[1]=new Employee1("李四",120);
        temp[2]=new Employee1("王五",135);
        temp[3]=new Employee1("小花",80);
        Arrays.sort(temp);
        for (Employee1 employee1 : temp) {
            System.out.println(employee1.toString());
        }
    }

输出结果:

在这里插入图片描述

总结:

此时因为我们已经重写了compareTo方法,这里我们用实现Comparable的方法进行了对象的排序。

二、Comparator 比较器接口

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

2.1、Comparator接口原码

特别说明

若一个类要实现Comparator接口:它一定要实现compareTo(T o1, T o2) 函数,但可以不实现 equals(Object obj) 函数。
为什么可以不实现 equals(Object obj) 函数呢? 因为任何类,默认都是已经实现了equals(Object obj)的。 Java中的一切类都是继承于java.lang.Object,在Object.java中实现了equals(Object obj)函数;所以,其它所有的类也相当于都实现了该函数。

package java.util;

public interface Comparator {

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

int compare()方法

返回值为:

小于0–>前一个对象小于后一个对象

大于0–>前一个对象大于后一个对象

等于0–>前一个对象等于后一个对象

2.2具体代码示例

背景

此时,我们在Employee1类的基础上,我们再添加一个升高,但是这个类的依旧实现了Comparable接口,重写了compareTo方法,并且这个方法按照工资薪水排序,此时我们如何能都不改变代码的前提下,重新对升高排序呢?

此时就引入了Comparator接口,我们实现这个接口的int compare方法,具体如下

public class Employee implements Comparable<Employee>{

    private String name;
    private double salary;
    private int height;

    public Employee(String name , double salary){
        this.name = name;
        this.salary = salary;
    }

    public Employee(String name , double salary, int height){
        this.name = name;
        this.salary = salary;
        this.height= height;
    }

    public String getName() {
        return name;
    }

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

    public Double getSalary() {
        return salary;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public void setSalary(Double salary) {
        this.salary = salary;
    }

    public void raiseSalary(double byPercent) {
        double raise = salary * byPercent / 100;
        salary += raise;
    }

    /**
     * 重写排序规则:
     * 定义我们的排序规则,用salary来排序
     * @param other
     * @return
     */
    @Override
    public int compareTo(Employee other) {
        return Double.compare(salary,other.salary);
    }
}

编写测试类:

public class EmployeeSortTest {
    public static void main (String[] args) {
        Employee[] staff = new Employee[4];
        staff[0] = new Employee ("张三" , 35000,175) ;
        staff[1] = new Employee ("李四" , 75000,165);
        staff[2] = new Employee ("王五" , 38000,180) ;
        staff[3] = new Employee ("小六" , 23000,153) ;
        //核心排序代码,对升高进行排序
        Arrays.sort(staff, Comparator.comparingInt(Employee::getHeight));
        //遍历数组结果
        for (Employee e : staff){
            System.out.println("name=" + e.getName() + " ,salary=" + e.getSalary()+" ,height="+e.getHeight());
        }
    }
}

对于核心排序代码,我们也可以用lambda表达式来编写:

        Arrays.sort(staff,((o1, o2) -> {
            if(o1.getHeight()==o2.getHeight()){
                return 0;
            }
            return o1.getHeight()-o2.getHeight();
        })) ;

原因;

从Arrays.sort()源码的角度分析,sort方法接收的参数类型,一个为数组类型,一个为Comparator对象,因为Comparator为接口所以不能实例化,但是我们可以用多态来指向它,我们可以声明Comparator的实现类对象指向这个接口,此时就可以调用这个接口。

当我们用lambda表达式时,也是创建了这个Comparator接口的具体实现方法,所以两者都可以进行排序,看读者的自己。

在这里插入图片描述

输出结果:

在这里插入图片描述

此时我们的这个数组对象就已经按照升高排序,实现需求。

三、Comparator 和 Comparable 比较

Comparable是排序接口;若一个类实现了Comparable接口,就意味着“该类支持排序”。

而Comparator是比较器;我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。

的自己。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入理解Java比较器(Comparable和Comparator) 的相关文章

随机推荐

  • React 学习之旅一

    React 学习之旅一 React 官网 版本要求 Node gt 8 10 和 npm gt 5 6 node v npm v 创建 React 项目 npx create react app my app Hook 它可以让你在不编写
  • customEventData的普通用法

    需要先用event来接受一些其他信息 然后传入的数值放在参数中 类型按钮按下 TypeButtonDown event value console log 按下 console log value 然后再button这里设置好eventDa
  • java 实现POI导入导出Excel

    package com chenxc utils excel import org apache poi hssf usermodel import org apache poi hssf util HSSFColor import org
  • 基于Django Template模式实现简单的注册、登录,表单提交

    最近在做一个简单的django项目 需求是能实现注册 登录 并且有一个提交评论 展示评论的功能 django做web项目是非常适合 前期熟悉对应的配置 熟悉框架结构 按照既定的模式进行二次开发即可完成一个完整的系统 项目目录结构如下 1 核
  • GPT4的1000+篇文章总结

    GPT4的1000 篇文章总结 本文收集和总结了有关GPT4的1000 篇文章 由于篇幅有限只能总结近期的内容 想了解更多内容可以访问 http www ai2news com 其分享了有关AI的论文 文章 图书 query 恐怖的GPT4
  • 页面触底自动加载 Vue 组件

    不管是 web 端还是移动端 信息流都是现在很流行的信息展示方式 信息流经常搭配自动加载一起使用以获得更好的使用体验 最近在使用 Vue 开发过程中也遇到了首页信息流自动加载的需求 大致了解了一下几个滚动自动加载组件 发现多数都是把内容放在
  • 如何理解jquery的$(".span").eq(0) 和 $(”.span“)[0]

    span class span 1 span span class span 2 span span class span 3 span span class span 4 span span 选择了4个span 都是jquery对象 可以
  • 第一章:走进scratch3.0

    第一章 Scratch中国 想象 创作 编程 分享 scratch cn cn 离线版桌面版下载 exe结尾是 windows版 dmg是 macOS 苹果 版 点击下方链接下载 链接 https pan baidu com s 1wwrK
  • ALtium 16等长布线、差分布线

    等长布线 1 先布好线 2 定义一个class design classes 下图右键net classes add classes 之后定义这个class的名字 例如dc 选择要等长的网络加入这个dc 之后close即可 3 tools
  • 毕业设计-基于机器学习的股票预测

    目录 前言 课题背景和意义 实现技术思路 一 传统股票预测模型 二 新型股票预测方法 实现效果图样例 最后 前言 大四是整个大学期间最忙碌的时光 一边要忙着备考或实习为毕业后面临的就业升学做准备 一边要为毕业设计耗费大量精力 近几年各个学校
  • ImportError: No module named psutil的解决

    系统版本 cat etc redhat release CentOS release 6 9 Final 跑python脚本的时候报错ImportError No module named psutil 于是想要用pip来安装 但是发现pi
  • 关于source中的TARGETLIBS和SOURCELIBS的区别

    摘自 http topic csdn net u 20090403 11 897684cc 3eca 40f4 90d7 88e501669efe html 转自微软MVP作者 ARM WinCE 1 Dirs文件 关于Dirs文件 就是指
  • Win10 环境配置 Github SSH Key

    使用 Git 关联远程仓库通常可以使用 HTTP 协议或者 SSH 协议 在使用上 SSH 只需要一次配置 之后提交操作都不需要进行用户密码验证 但是 HTTP 方式每次 Push 操作都需要验证用户名和密码 当然 HTTP 方式更方便开源
  • 互联网摸鱼日报(2023-09-13)

    互联网摸鱼日报 2023 09 13 36氪新闻 节能减排 科技降碳 上海打造绿色商场的N种实践 36氪独家 美团管理层迎来重大变化 5位业务负责人晋升为副总裁 险资牵手上市公司狂出手 800亿给了谁 没空旅行的年轻人 开始互换特产 国产手
  • 手把手教你用python一键抢12306火车票(附代码)

    哈喽 哈喽 一年一度的抢火车票大战正式拉开序幕 然饿大多数人碰到的是这种情况 当你满心期待摩拳擦掌准备抢票的时候 你会发现一票难求 想回趟家真难 那么作为程序猿的你 当然要用程序猿的方式来抢票 下面分享用python来抢票 欢迎关注公众号
  • 电脑照片,怎么把电脑照片传到iphone手机 将电脑照片传到iphone方法【图文】

    使用苹果设备的人一定知道苹果自带的iOS系统是不可以随便进行数据的交换的 必须使用iTunes软件进行传输 但是让一些对不懂苹果设备的人带来了很多困扰 电脑当中的图片如何传输到苹果设备当中呢 下面我们就一起来看看怎么把电脑照片传到iphon
  • ZOJ 1610 Count the Colors

    Problem acm zju edu cn onlinejudge showProblem do problemCode 1610 Reference blog csdn net shuangde800 article details 8
  • 单元二:全桥MOS/IGBT电路(后端全桥电路的搭建)

    本篇博客是全桥MOS IGBT电路搭建的介绍 想了解全桥电路的驱动部分请看博主的单元一 全桥驱动电路详解 感兴趣的可以添加博主QQ 2859340499 B站对应讲解本文链接 逆变电路 Inverter Circuit 是与整流电路 Rec
  • 华为荣耀七能升级鸿蒙系统吗,华为鸿蒙系统来了,你知道哪些华为手机荣耀手机可以升级吗?...

    从鸿蒙系统第一次开始登场 到现在慢慢有许多鸿蒙系统设备出现 手机市场的格局似乎又要升级变化了 科技树儿了解到 在某数码博主经过和相关人员的沟通核实之后 目前暂定的是搭载华为麒麟710芯片以上的机型 无论华为或荣耀 都会升级华为鸿蒙Harmo
  • 深入理解Java比较器(Comparable和Comparator)

    深入理解Java比较器 Comparable和Comparator 文章目录 深入理解Java比较器 Comparable和Comparator 一 Comparable 1 Comparable 接口定义 二 Comparator 比较器