java comparable与_详解Java中Comparable和Comparator接口的区别

2023-10-31

详解Java中Comparable和Comparator接口的区别

本文要来详细分析一下Java中Comparable和Comparator接口的区别,两者都有比较的功能,那么究竟有什么区别呢,感兴趣的Java开发者继续看下去吧。

Comparable 简介

Comparable 是排序接口。

若一个类实现了Comparable接口,就意味着“该类支持排序”。  即然实现Comparable接口的类支持排序,假设现在存在“实现Comparable接口的类的对象的List列表(或数组)”,则该List列表(或数组)可以通过 Collections.sort(或 Arrays.sort)进行排序。

此外,“实现Comparable接口的类的对象”可以用作“有序映射(如TreeMap)”中的键或“有序集合(TreeSet)”中的元素,而不需要指定比较器。

Comparable 定义

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

package java.lang;

import java.util.*;

public interface Comparable {

public int compareTo(T o);

}

说明:

假设我们通过 x.compareTo(y) 来“比较x和y的大小”。若返回“负数”,意味着“x比y小”;返回“零”,意味着“x等于y”;返回“正数”,意味着“x大于y”。

Comparator 简介

Comparator 是比较器接口。

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

也就是说,我们可以通过“实现Comparator类来新建一个比较器”,然后通过该比较器对类进行排序。

Comparator 定义

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

package java.util;

public interface Comparator {

int compare(T o1, T o2);

boolean equals(Object obj);

}

说明:

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

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

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

Comparator 和 Comparable 比较

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

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

我们不难发现:Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。

我们通过一个测试程序来对这两个接口进行说明。源码如下:

import java.util.*;

import java.lang.Comparable;

/**

* @desc "Comparator"和“Comparable”的比较程序。

* (01) "Comparable"

* 它是一个排序接口,只包含一个函数compareTo()。

* 一个类实现了Comparable接口,就意味着“该类本身支持排序”,它可以直接通过Arrays.sort() 或 Collections.sort()进行排序。

* (02) "Comparator"

* 它是一个比较器接口,包括两个函数:compare() 和 equals()。

* 一个类实现了Comparator接口,那么它就是一个“比较器”。其它的类,可以根据该比较器去排序。

*

* 综上所述:Comparable是内部比较器,而Comparator是外部比较器。

* 一个类本身实现了Comparable比较器,就意味着它本身支持排序;若它本身没实现Comparable,也可以通过外部比较器Comparator进行排序。

*/

public class CompareComparatorAndComparableTest{

public static void main(String[] args) {

// 新建ArrayList(动态数组)

ArrayList list = new ArrayList();

// 添加对象到ArrayList中

list.add(new Person("ccc", 20));

list.add(new Person("AAA", 30));

list.add(new Person("bbb", 10));

list.add(new Person("ddd", 40));

// 打印list的原始序列

System.out.printf("Original sort, list:%s\n", list);

// 对list进行排序

// 这里会根据“Person实现的Comparable接口”进行排序,即会根据“name”进行排序

Collections.sort(list);

System.out.printf("Name sort, list:%s\n", list);

// 通过“比较器(AscAgeComparator)”,对list进行排序

// AscAgeComparator的排序方式是:根据“age”的升序排序

Collections.sort(list, new AscAgeComparator());

System.out.printf("Asc(age) sort, list:%s\n", list);

// 通过“比较器(DescAgeComparator)”,对list进行排序

// DescAgeComparator的排序方式是:根据“age”的降序排序

Collections.sort(list, new DescAgeComparator());

System.out.printf("Desc(age) sort, list:%s\n", list);

// 判断两个person是否相等

testEquals();

}

/**

* @desc 测试两个Person比较是否相等。

* 由于Person实现了equals()函数:若两person的age、name都相等,则认为这两个person相等。

* 所以,这里的p1和p2相等。

*

* TODO:若去掉Person中的equals()函数,则p1不等于p2

*/

private static void testEquals() {

Person p1 = new Person("eee", 100);

Person p2 = new Person("eee", 100);

if (p1.equals(p2)) {

System.out.printf("%s EQUAL %s\n", p1, p2);

} else {

System.out.printf("%s NOT EQUAL %s\n", p1, p2);

}

}

/**

* @desc Person类。

* Person实现了Comparable接口,这意味着Person本身支持排序

*/

private static class Person implements Comparable{

int age;

String name;

public Person(String name, int age) {

this.name = name;

this.age = age;

}

public String getName() {

return name;

}

public int getAge() {

return age;

}

public String toString() {

return name + " - " +age;

}

/**

* 比较两个Person是否相等:若它们的name和age都相等,则认为它们相等

*/

boolean equals(Person person) {

if (this.age == person.age && this.name == person.name)

return true;

return false;

}

/**

* @desc 实现 “Comparable” 的接口,即重写compareTo函数。

* 这里是通过“person的名字”进行比较的

*/

@Override

public int compareTo(Person person) {

return name.compareTo(person.name);

//return this.name - person.name;

}

}

/**

* @desc AscAgeComparator比较器

* 它是“Person的age的升序比较器”

*/

private static class AscAgeComparator implements Comparator {

@Override

public int compare(Person p1, Person p2) {

return p1.getAge() - p2.getAge();

}

}

/**

* @desc DescAgeComparator比较器

* 它是“Person的age的升序比较器”

*/

private static class DescAgeComparator implements Comparator {

@Override

public int compare(Person p1, Person p2) {

return p2.getAge() - p1.getAge();

}

}

}

下面对这个程序进行说明。

a) Person类定义。如下:

private static class Person implements Comparable{

int age;

String name;

...

/**

* @desc 实现 “Comparable” 的接口,即重写compareTo函数。

* 这里是通过“person的名字”进行比较的

*/

@Override

public int compareTo(Person person) {

return name.compareTo(person.name);

//return this.name - person.name;

}

}

说明:

(01) Person类代表一个人,Persong类中有两个属性:age(年纪) 和 name“人名”。

(02) Person类实现了Comparable接口,因此它能被排序。

b) 在main()中,我们创建了Person的List数组(list)。如下:

// 新建ArrayList(动态数组)

ArrayList list = new ArrayList();

// 添加对象到ArrayList中

list.add(new Person("ccc", 20));

list.add(new Person("AAA", 30));

list.add(new Person("bbb", 10));

list.add(new Person("ddd", 40));

c) 接着,我们打印出list的全部元素。如下:

// 打印list的原始序列

System.out.printf("Original sort, list:%s\n", list);

d) 然后,我们通过Collections的sort()函数,对list进行排序。

由于Person实现了Comparable接口,因此通过sort()排序时,会根据Person支持的排序方式,即 compareTo(Person person) 所定义的规则进行排序。如下:

// 对list进行排序

// 这里会根据“Person实现的Comparable接口”进行排序,即会根据“name”进行排序

Collections.sort(list);

System.out.printf("Name sort, list:%s\n", list);

e) 对比Comparable和Comparator

我们定义了两个比较器 AscAgeComparator 和 DescAgeComparator,来分别对Person进行 升序 和 降低 排序。

e.1) AscAgeComparator比较器

它是将Person按照age进行升序排序。代码如下:

/**

* @desc AscAgeComparator比较器

* 它是“Person的age的升序比较器”

*/

private static class AscAgeComparator implements Comparator {

@Override

public int compare(Person p1, Person p2) {

return p1.getAge() - p2.getAge();

}

}

e.2) DescAgeComparator比较器

它是将Person按照age进行降序排序。代码如下:

/**

* @desc DescAgeComparator比较器

* 它是“Person的age的升序比较器”

*/

private static class DescAgeComparator implements Comparator {

@Override

public int compare(Person p1, Person p2) {

return p2.getAge() - p1.getAge();

}

}

f) 运行结果

运行程序,输出如下:

Original sort, list:[ccc - 20, AAA - 30, bbb - 10, ddd - 40]

Name sort, list:[AAA - 30, bbb - 10, ccc - 20, ddd - 40]

Asc(age) sort, list:[bbb - 10, ccc - 20, AAA - 30, ddd - 40]

Desc(age) sort, list:[ddd - 40, AAA - 30, ccc - 20, bbb - 10]

eee - 100 EQUAL eee - 100

如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

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

java comparable与_详解Java中Comparable和Comparator接口的区别 的相关文章

  • 多个Ajax请求成功后再执行后续方法

    经常会遇到需要ajax请求完毕后调用某方法 这次是多个ajax请求成功后 用它们返回的数据传参给回调方法 查询了一下 可以用jquery中的 when 使用方法如下 when ajax ajax ajax done function a1
  • centos6安装jenkins配置及使用

    本文的安装步骤说明环境为 centos6 9操作系统 jenkins2 138 安装jenkins 下载rpm文件 下载地址 https pkg jenkins io redhat 该说明中使用的是jenkins 2 138 1 1 noa
  • typora 快速复制excel到typora

    思想是把表格转换成html格式 复制到typora中 然后点击右上角 红色框的html 点击对号 就可以切换到表格了 有免费在线的切换工具 参考 http pressbin com tools excel to html table ind
  • 小孩子有没有学机器人编程的必要

    小孩子有没有学机器人编程的必要 对于很多的家长们来说 孩子的学习一直都是他们十分关心和重视的一件事情 很多的家长在培养孩子的学习方面也可以说是十分的用心的 他们会给孩子选择一些能够提升孩子能力的课程 就拿现在很多的家长想要孩子去学习机器人编
  • 在python中使用最小二乘法画出拟合曲线_基于jupyter notebook的python编程-----运用最小二乘法,导入文件数据模拟一元线性回归分析...

    基于jupyter notebook的python编程 运用最小二乘法 导入文件数据模拟一元线性回归分析 用最小二乘法模拟一元线性回去曲线的目录 一 运行jupyter notebook 搭建python环境 1 打开Windows终端命令
  • 预防死锁的3种方法

    1 采用资源的静态预分配策略 破坏 部分分配 条件 2 允许进程剥夺使用其他进程占用的资源破坏 不可剥夺 条件 3 采用资源有序分配法 破坏 环路 条件
  • 2022黑马SpringBoot跟学笔记(二)

    2022黑马SpringBoot跟学笔记 二 2 4 多环境配置 2 4 1 yaml文件 2 4 2 properties文件 2 4 3 命令行启动参数设置 2 4 4多环境开发控制 2 5 配置文件分类 2 5 1 代码演示 2 5
  • 谨防商家套路——一定要一样一样功能问好自己所要的功能——常年购物都被打了眼【伸手党避坑】

    本人淘宝购物十几年了 从淘宝刚出来不久就开始 自从PDD购物被骗后 觉得自己辨别商家套路能力有限 所以转战淘宝 很遗憾的是 在taobao也会有这种误导消费者的商家 常用的商家套路咱们就不说了 明眼都能看出来 但是利用惯性思维给人下套的 我
  • vue3内置组件(Teleport组件,Fragment组件)-传送组件,减少层级

    一 传送组件 Teleport组件 可将组件移动到 DOM 中 Vue app 之外的其他位置 主要是为了解决一些特殊场景下模态对话框组件 组件的渲染 例子 模拟UI框架对话框组件 App vue
  • leetcode-每日一道算法题

    字符串转换整数 atoi 请你来实现一个 myAtoi string s 函数 使其能将字符串转换成一个 32 位有符号整数 类似 C C 中的 atoi 函数 函数 myAtoi string s 的算法如下 读入字符串并丢弃无用的前导空
  • 韩信点兵问题,鸡兔同笼问题,闰年判断问题等,我用Python瞬间搞定(13)

    小朋友们好 大朋友们好 我是猫妹 一名爱上Python编程的小学生 欢迎和猫妹一起 趣味学Python 今日主题 最近猫妹一直在练习Python编程 有些习题真是经典啊 比如韩信点兵问题 比如鸡兔同笼问题等 这些问题 第一次遇到 真是没有思
  • 第0章-JDK的安装与配置

    JDK 8 的安装与配置 本系列文章参考了尚硅谷的课件文档及其他同学的学习笔记 1 安装 1 1 打开网页下载 https www oracle com 下载对应平台的合适的 JDK 版本 1 2 开始安装 双击下载的 exe 如 jdk
  • js阻止事件冒泡

    js阻止事件冒泡
  • 【ELK系列二】es的UI界面elasticsearch-head插件安装

    安装elasticsearch head插件 由于es服务启动之后 访问界面比较丑陋 为了更好的查看索引库当中的信息 我们可以通过安装elasticsearch head这个插件来实现 这个插件可以更方便快捷的看到es的管理界面 1 com
  • 爬虫学习4——Xpath爬取网页信息

    xpath是在XML文档中搜索内容的一门语言 我们常见的html是xml的一个子集 目录 安装lxml模块 获取网页数据 text 拿文本 xpath使用 1 选择同种标签的第一个 a href 根据属性href的值选择特定标签 表示后代
  • 《Docker技术入门与实战》学习笔记——第一部分 基础入门

    文章目录 0 前言 1 1 docker 镜像 1 2 docker 容器 1 3 docker 仓库 2 容器的生命周期 3 docker 命令索引 学习材料 0 前言 近期 工作中docker用的比较多 由于之前并没有怎么使用过dock
  • QT 环境搭建

    qt环境搭建 转载于 http blog csdn net gotosola article details 20397385 0 tsina 1 37407 397232819ff9a47a7b7e80a40613cfe1 Qt在Wind
  • Oracle 生成UUID

    select rawtohex sys guid from dual 文章质量建议 感谢你的创作 你可以考虑下面的改进以获得更多流量支持 增加更完备的描述 提供代码 减少外链 增加投票来和读者互动 更多建议
  • SpringBoot之bean解析(四)

    IOC思想解析 IOC 控制反转 全称为 Inverse of Control 从字面上理解就是控制反转了 将对在自身对象中的一个内置对象的控制反转 反转后不再由自己本身的对象进行控制这个内置对象的创建 而是由第三方系统去控制这个内置对象的

随机推荐

  • linux 配置服务开机自启动之chkconfig(Linux 运行级别)

    文章目录 linux 配置服务开机自启动 systemd 和 chkconfig add 设置开机自启动有什么区别 一 如何让一个服务或脚本开机自启动 1 三种解决方案 2 systemd 和 chkconfig 二 chkconfig 1
  • [OpenGL]射线拾取RayPicking---(2)拾取三角面

    Vries的教程是我看过的最好的可编程管线OpenGL教程 没有之一 但没有讲关于拾取 Picking 的章节 而这个功能的确很重要 就自己试着写写看了 核心代码 参考 网址如下 别问 问就是抄 https www cnblogs com
  • MATLAB自相关分析xcorr

    目录 自相关定义 xcorr的应用 举个栗子 自相关定义 信号 x t x t x t 的自相关函数定义为 其中 T为信号 x
  • 2016.5.23

    2016 5 23 news from BBC China s Science Revolution 这篇文章非常棒 推荐阅读 今天只完成4个部分 明天继续mark introduction From building the bigges
  • 将 InputStream 流转成 MultipartFile

    MultipartFile是一个接口 有一个MockMultipartFile实现类 里面有构造方法可以直接将输入流转为MutipartFile对象 MultipartFile File new MockMultipartFile file
  • @angular前端项目代码优化:构建Api Tree

    前颜 yan 在前端项目的开发过程中 往往后端会给到一份数据接口 本文简称api 为了减少后期的维护以及出错成本 我的考虑是希望能够找到这么一种方法 可以将所有的api以某种方式统一的管理起来 并且很方便的进行维护 比如当后端修改了api名
  • 三维重建(单目、双目、多目、点云、SFM、SLAM)

    1 相机几何与标定 1 1 相机模型中的坐标系 1 2 四种坐标系之间的转换 1 3 相机内参 1 4 相机标定 2 传统三维重建 2 1 RGBD三维重建 2 1 1 KinectFusion 2 1 2 BundleFusion 2 1
  • CentOS7 Failed to start LSB: Bring up/down解决方法

    刚刚装好的虚拟机突然不能上网了 报错很诡异 具体报错如下 etc init d network restart Restarting network via systemctl Job for network service failed
  • three.js加载fbx并解析骨骼动画

    three js加载fbx并解析骨骼动画 话不多说 上代码
  • SpringBoot如何打包项目?

    我们打包SpringBoot项目一般是打包成jar包或者war包 jar包和war包最大的区别在于jar包打出来的可直接运行 我们可以直接进行访问 因为他内前置了tomcat服务器 但是war包在打包的时候会提前移除tomcat相关组件 我
  • Verilog入门——Quartus2基础使用

    一 新建工程 1 打开Quartus2 2 点击菜单栏中的 file 选择 New Project Wizard 3 点击Next 4 选择工程存储路径 5 输入工程名字 6 点击Next 7 选择fpga类型和型号 根据自己的板子型号选择
  • 最简单的DRM应用程序 (single-buffer)

    在上一篇DRM Direct Rendering Manager 学习简介 中 我们学习了DRM的基本概念以及基本组成元素 从本篇开始 我将以示例代码的形式 给大家分享学习DRM驱动开发的整个学习过程 在学习DRM驱动之前 应该首先了解如何
  • 【java】ssh the connection is not authenticated

    文章目录 1 概述 1 概述 首先参考 java java ssh 远程执行命令 并且获取执行的结果 然后讲述一下 这个问题 这是一段很久的代码 以前是能正常工作的 环境如下 Docker flink node 这里ssh kafka no
  • QT笔记-窗体设置

    1 窗体设置 个窗体初始运行最大化 setWindowState Qt WindowMaximized 获取屏幕分别率 并设置窗体固定大小 QScreen screen QGuiApplication primaryScreen QRect
  • MySQL 日期相减得到秒、分、天

    文章目录 一 MySQL中两个DateTime字段相减 二 MySQL中两个Time字段相减 一 MySQL中两个DateTime字段相减 这种方式两字段跨天 月 年都无问题 得到两个日期字段之间的秒数 selec t UNIX TIMES
  • 医学影像组学之病理切片分割(免费训练数据,标注数据,免费代码,免费教程)三天走完影像组学全部流程

    谁规定说影像组学只能从写代码 学语言耗费半年时间才能开始实验 三天让你走完影像组学完整流程 训练数据已经集成好 标注数据也已备好 代码也备好了 训练过程是这样的 另外笔者整理了其他影像组学的教学小视频 有兴趣的可以在下面评论
  • 华为HCIE云计算之部署Fusion Access及云桌面发放实战

    华为HCIE云计算之部署Fusion Access及云桌面发放实战 一 在FC上安装FA01虚拟机 1 选择创建类型 2 创建虚拟机基本配置 3 创建数据存储 4 选择虚拟机配置 5 虚拟机创建完成 二 安装FA01系统 1 进入系统安装界
  • 以太坊入门学习资料

    区块链分类 区块链按照访问和管理权限分为公有链 联盟链和私有链 公有链 完全开放 所有节点均可加入 代表链 比特币Bitcoin 以太坊Ethereum 联盟链 有多个组织和机构共同管理 获得组织和机构许可的节点可以加入 代表链 超级账本H
  • uniapp弹窗实现

  • java comparable与_详解Java中Comparable和Comparator接口的区别

    详解Java中Comparable和Comparator接口的区别 本文要来详细分析一下Java中Comparable和Comparator接口的区别 两者都有比较的功能 那么究竟有什么区别呢 感兴趣的Java开发者继续看下去吧 Compa