超详细的java Comparable,Comparator接口解析
前言
Hello大家好呀,在java中我们常常涉及到对象的比较,不同于基本数据类型,对于我们的自定义对象,需要我们自己去建立比较标准,例如我们自定义一个People类,这个类有name和age两个属性,那么问题来了,你如何比较两个人呢?很明显这个时候我们只有建立一个比较标准,只根据名字或者年龄比较,这个时候就需要Comparable和Comparator接口了,下面我将带领大家学习这两个接口
一,二者区别
首先呢,我想先为大家区别一下二者:Comparable与Comparator在逻辑上相似,都是根据比较对象的大小不同返回一个整型。但是类重写Comparable的compareTo方法只有一个,通常定义在要比较的类内部,由类的对象调用传入另一个该类的对象来比较,这当然有它的局限性,因为一个类中只能有一个compareTo方法,因此,只能指定一种比较标准,就像在刚才举例的Person类中重写comparable方法的话,只能指定按照名字或者年龄直接一种来排,但是在某些即需要我们根据名字排序,也需要我们根据年龄来排序的情境中就头疼了,因为compareTo方法没有重载,这个时候就需要Comparator接口,我们可以定义不同的按照不同标准比较两个对象的类来运用compare方法比较,现在听不懂也没关系,下面会为大家说明代码细节。
二,Comparable接口
以前面的Person类为例让类继承Comparable接口,同时按住Alt+Enter按键一直按到底,编译器会自动生成一段代码

这段代码没什么稀奇的,我们肯定是要重写它,但是我们需要注意它是传了一个Object的参数,(当然我们也可以自己修改成Person)这个参数需要我们强转成我们需要比较的对象才能够使用,那么我们先根据较简单的年龄比较,因为他是一个整形数据,如果调用该方法的对象年龄大于传入对象是返回一个大于0的数,他们年龄相等时返回0,否则返回一个小于0的数,于是我们得到了这样一段代码

当然,这段代码可不可以优化呢?显然,因为是整型数据的比较,可以写成下面的形式

ok那么我们就实现了用年龄比较两个Person对象的方法,后面内容我们会用这个方法实现一个排序算法这里先不测试这个方法继续往下讲,那么显然,对于String类型的name,不支持我们减号来比较两个对象的属性该怎么办呢?答案是,再调用一次ConpareTo方法

当然,这个时候调用的就是String内部的compareTo方法,我们不必关心代码实现细节,这也再次体现了封装的好处,我们不妨看看String是怎么实现这个方法的,按住ctrl鼠标点击这个方法便可以查看源码

当然我们这个时候,只要会用这个方法就行,代码放在下面,大家也能看出它的局限性,就是说下面我写根据姓名比较Person对象时必须把写过的根据年龄比较的代码注调
public class Test {public static void main(String[] args) {}
}
class Person implements Comparable {String name;int age;public Person(String name, int age) {this.name = name;this.age = age;}
// @Override
// public int compareTo(Object o) {
// Person tmp=(Person) o;//使用之前需强转
// return this.age-tmp.age;
// }@Overridepublic int compareTo(Object o) {Person tmp=(Person) o;//使用之前需强转return this.name.compareTo(tmp.name);}
}
三,Comparator接口
实现Comparator的compare方法与compareTo方法初始情况知识compare方法多了一个参数

我们已经说过最好新建一个比较类根据不同标准比较,与compareTo方法的区别是这里不能由对象调用,也就是不能存在this,然后代码实现细节和compareTo差别不大,大家可以看看下面这段代码思考一下Comparator接口怎么实现根据不同标准比较的
import java.util.Comparator;
public class Test {public static void main(String[] args) {}
}
class Person {String name;int age;public Person(String name, int age) {this.name = name;this.age = age;}
}
class AgeCompare implements Comparator<Person>{//这里<Person>是声明这个接口用于比较Person类,这部分知识后面还会讲@Overridepublic int compare(Person person, Person t1) {return person.age-t1.age;}
}
class NameCompare implements Comparator<Person>{@Overridepublic int compare(Person person, Person t1) {return person.name.compareTo(t1.name);}
}
我们再比较时只需实例化一个比较类在调用方法传入两给person对象就好啦
四,冒泡排序实现排序person对象
代码实现细节都放在注释里啦,先上代码
import java.util.Comparator;public class Test {public static void main(String[] args) {Person person1=new Person("a",15);Person person2=new Person("b",12);Person person3=new Person("c",17);Person person4=new Person("d",13);Person person5=new Person("e",19);//实例化五个对象Person[] people={person1,person5,person3,person2,person4};//乱序Sort.sort(people);//这个时候就排好了System.out.println(people[0]);System.out.println(people[1]);System.out.println(people[2]);System.out.println(people[3]);System.out.println(people[4]);}
}
class Person implements Comparable{String name;int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic int compareTo(Object o) {return this.age-((Person)o).age;}
}class Sort {public static void sort(Comparable[] comparable) {//注意这里用接口数组表示实现了这个接口也就是这个数组一定是可比较的for (int i = 0; i < comparable.length - 1; i++) {for (int j = 0; j < comparable.length - 1; j++) {//标准冒泡排序if (comparable[j].compareTo(comparable[j + 1]) > 0) {//因为比较的是任意类型数据,这里一定是调用我们重写的compareTo方法Comparable tmp=comparable[j];comparable[j]=comparable[j+1];comparable[j+1]=tmp;}}}}
}

注意我们如果要修改排序顺序选择修改compareTo方法,修改一行代码即可

改为


同样,要根据名字排序也只需动compareTo方法


这样我们的排序就完成啦
本期博客就到这里,感谢大家阅读,我们下期见
相关文章:
超详细的java Comparable,Comparator接口解析
前言 Hello大家好呀,在java中我们常常涉及到对象的比较,不同于基本数据类型,对于我们的自定义对象,需要我们自己去建立比较标准,例如我们自定义一个People类,这个类有name和age两个属性,那么问…...
Java使用GDAL来解析KMZ及KML实战
目录 前言 一、在GQIS中浏览数据 1、关于空间参考 2、属性表格 二、GDAL的相关驱动及解析实战 1、GDAL中的KMZ驱动 2、GDAL实际解析 三、数据解析成果 1、KML解析结果 2、KMZ文件入库 四、总结 前言 在前面的博客中讲过纯Java实现Google地图的KMZ和KML文件的解析&…...
【vuex小试牛刀】
了解vuex核心概念请移步 https://vuex.vuejs.org/zh/ # 一、初始vuex # 1.1 vuex是什么 就是把需要共享的变量全部存储在一个对象里面,然后将这个对象放在顶层组件中供其他组件使用 父子组件通信时,我们通常会采用 props emit 这种方式。但当通信双方不…...
React - 实现走马灯组件
一、实现效果 二、源码分析 import {useRef, useState} from "react";export const Carousel () > {const images [{id: 3, url: https://sslstage3.sephorastatic.cn/products/2/4/6/8/1/6/1_n_new03504_100x100.jpg}, {id: 1, url: https://sslstage2.sephor…...
【学习笔记】Windows GDI绘图(十三)动画播放ImageAnimator(可调速)
文章目录 前言定义方法CanAnimate 是否可动画显示Animate 动画显示多帧图像UpdateFramesStopAnimate终止动画Image.GetFrameCount 获取动画总帧数Image.GetPropertyItem(0x5100) 获取帧延迟 自定义GIF播放(可调速) 前言 在前一篇文章中用到ImageAnimator获取了GIF动画的一些属…...
fps游戏如何快速定位矩阵
fps游戏如何快速定位矩阵 矩阵特点: 1、第一行第一列值的范围在**-1 ---- 1**之间,如果开镜之后值会变大。 2、第一行第三列的值始终为 0。 3、第一行第四列 的值比较大 , >300或者**<-300**。 根据这三个特点,定位矩阵已经足够了…...
【机器学习基础】Python编程06:五个实用练习题的解析与总结
Python是一种广泛使用的高级编程语言,它在机器学习领域中的重要性主要体现在以下几个方面: 简洁易学:Python语法简洁清晰,易于学习,使得初学者能够快速上手机器学习项目。 丰富的库支持:Python拥有大量的机器学习库,如scikit-learn、TensorFlow、Keras和PyTorch等,这些…...
R可视化:生存分析森林图
在R语言中,使用forestplot包来绘制生存分析的森林图是一个专业且直观的方式来展示各种风险因素或治疗对生存结果的影响。森林图(Forest Plot)常用于展示多项研究的效应量和其可信区间,尤其在生存分析中,它可以清晰地显示不同变量或因素对生存时间的影响程度和统计显著性。…...
一个 python+tensorFlow训练1万张图片分类的简单直观例子( 回答由百度 AI 给出 )
问题:给定一个文件夹 train_images,里面有10000张30*30像素的灰度值图片,第1~第10000张图片的名称分别为 00001.png、 00002.png、... 09999.png、10000.png,train_images 下面还有一个 image_category_map.txt文件, 文件的内容…...
DBeaver无法连接Clickhouse,连接失败
DBeaver默认下载的是0.2.6版本的驱动,但是一直连接失败: 报错提示 解决办法 点击上图中的Open Driver Configuration点击库 - 重置为默认状态在弹出的窗口中修改驱动版本号为0.2.4或者其他版本(我没有试用过其他版本)࿰…...
python基础实例
下一个更大的数 定义一个Solution类,用于实现next_great方法 class Solution: def next_great(self, nums1, nums2): # 初始化一个空字典answer,用于存储答案 answer {} # 初始化一个空列表stack,用于存储待比较的数字 stack [] # 遍历nu…...
ADASIS V2 协议-1
ADAS V2协议-1 1 简介2 版本控制3 ADASIS v23.1 ADASIS v2 Horizon (地平线)3.2 ADASIS v2的构建3.3 ADASIS v2 Horizon Provider (ADAS V2地平线提供者)3.4 paths and offsets (路径和偏移量)3.5 Path Pro…...
人工智能安全风险分析及应对策略
文│中国移动通信集团有限公司信息安全管理与运行中心 张峰 江为强 邱勤 郭中元 王光涛 人工智能(AI)是引领新一轮科技革命和产业变革的关键技术。人工智能赋能网络安全的同时,也会带来前所未有的安全风险。本文在介绍人工智能技术赋能网络安…...
Python驱动下的AI革命:技术赋能与案例解析
在当今这个信息化、数据化的时代,人工智能(AI)已经成为推动社会发展的重要力量。而Python,作为一种简单易学、功能强大的编程语言,在AI领域的应用中发挥着至关重要的作用。本文将探讨Python在AI领域的应用、其背后的技…...
JavaScrip轮播图
前言 在网页设计中,轮播图(Carousel)已经成为一种常见的元素,用于展示一系列的图片或内容卡片。它们不仅能够吸引用户的注意力,还能节省空间,使得用户可以在有限的空间内获得更多的信息。今天,我…...
达梦8 网络中断对系统的影响
测试环境:三节点实时主从 版本:--03134283938-20221019-172201-20018 测试1 系统没有启动确认监视器 关闭节点3网卡 登录节点1检查主库状态 显示向节点2发送归档成功,但无法收到节点3的消息,节点1挂起 日志报错如下…...
OpenAI发布GPT-4思维破解新策略,Ilya亦有贡献!
OpenAI正在研究如何破解GPT-4的思维,并公开了超级对齐团队的工作,Ilya Sutskever也在作者名单中。 论文地址:https://cdn.openai.com/papers/sparse-autoencoders.pdf 代码:https://github.com/openai/sparse_autoencoder 特征可…...
[消息队列 Kafka] Kafka 架构组件及其特性(二)Producer原理
这边整理下Kafka三大主要组件Producer原理。 目录 一、Producer发送消息源码流程 二、ACK应答机制和ISR机制 1)ACK应答机制 2)ISR机制 三、消息的幂等性 四、Kafka生产者事务 一、Producer发送消息源码流程 Producer发送消息流程如上图。主要是用…...
faiss ivfpq索引构建
假设已有训练好的向量值,构建索引(nlist和随机样本按需选取) import numpy as np import faiss import pickle from tqdm import tqdm import time import os import random# 读取嵌入向量并保留对应关系 def read_embeddings(directory, ba…...
ffmpeg视频编码原理和实战-(2)视频帧的创建和编码packet压缩
源文件: #include <iostream> using namespace std; extern "C" { //指定函数是c语言函数,函数名不包含重载标注 //引用ffmpeg头文件 #include <libavcodec/avcodec.h> } //预处理指令导入库 #pragma comment(lib,"avcodec.…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...
windows系统MySQL安装文档
概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...
阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)
cd /home 进入home盘 安装虚拟环境: 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境: virtualenv myenv 3、激活虚拟环境(激活环境可以在当前环境下安装包) source myenv/bin/activate 此时,终端…...
云原生安全实战:API网关Envoy的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关 作为微服务架构的统一入口,负责路由转发、安全控制、流量管理等核心功能。 2. Envoy 由Lyft开源的高性能云原生…...
2.2.2 ASPICE的需求分析
ASPICE的需求分析是汽车软件开发过程中至关重要的一环,它涉及到对需求进行详细分析、验证和确认,以确保软件产品能够满足客户和用户的需求。在ASPICE中,需求分析的关键步骤包括: 需求细化:将从需求收集阶段获得的高层需…...
spring boot使用HttpServletResponse实现sse后端流式输出消息
1.以前只是看过SSE的相关文章,没有具体实践,这次接入AI大模型使用到了流式输出,涉及到给前端流式返回,所以记录一下。 2.resp要设置为text/event-stream resp.setContentType("text/event-stream"); resp.setCharacter…...
