详解Comparable和Comparator

article/2025/9/29 4:58:43

目录

Comparable接口

Comparator接口


Comparable接口

Comparable接口在源码中的声明:

public interface Comparable<T> {public int compareTo(T o);
}

可以看到,只要一个compareTo方法,也就是说,实现Comparable接口的类都要重写compareTo方法。

 Comparable接口的功能就是用于对象之间的比较。那个也就是说比较的主要实现逻辑就在compareTo方法中。

package Blog;import java.util.Arrays;class Student implements Comparable<Student> {public int score;public String name;public Student() {}public Student(int score, String name) {this.score = score;this.name = name;}@Overridepublic String toString() {return "Student{" +"score=" + score +", name='" + name + '\'' +'}';}@Overridepublic int compareTo(Student o) {return this.score - o.score;}
}
public class test {public static void main(String[] args) {Student student1 = new Student(90, "abc");Student student2 = new Student(80, "bdc");System.out.println(student1.compareTo(student2));}
}

可以看到上面代码和结果,我们有两个student对象,这个两个对象之间我们想要知道谁大,那么我们就可以实现 Comparable 重写compareTo方法。在compareTo方法定义比较规则,this就是那个对象调用的compareTo方法,O就是要和那个对象进行比较。

我们在compareTo方法中定义的是以score来比较的。我们还可以定义以name进行比较。

   @Overridepublic int compareTo(Student o) {return this.name.compareTo(o.name);}

上述代码就是以name字段来比较大小。

可以看出在compareTo中再次的调用了compareTo方法,但是需要注意的是,这个compareTo方法不是我们写的这个方法,而是String的compareTo方法。因为name是String类型的。String类也是实现了comparable接口的。

我们经常用到的排序方法,Arrays.sort(); 这个方法是我们一直在使用的。

但是我们基本上使用都是用于基本数据类型,基本数据类型在排序过程进行比较是简单明了的。

那么我们如果排序的是一个对象呢,在排序的过程是如果进行比较的呢?

class Student {public int score;public String name;public Student() {}public Student(int score, String name) {this.score = score;this.name = name;}@Overridepublic String toString() {return "Student{" +"score=" + score +", name='" + name + '\'' +'}';}
}public class test {public static void main(String[] args) {Student student1 = new Student(90, "张三");Student student2 = new Student(80, "王三");Student student3 = new Student(70, "李三");Student student4 = new Student(40, "高三");Student student5 = new Student(50, "马三");Student[] students = {student1, student2, student3, student4, student5};Arrays.sort(students);System.out.println(Arrays.toString(students));}
}

可以看到上述的代码中,我们调用了sort方法来对Student对象数组进行排序。

但是执行代码之后,我们发现报ClassCastException错误了。

这是因为我们的数组是对象数组,里面有很多的不同的属性,那么就造成在排序的过程中编译器不知道我们是以什么规则来进行排序的。

此时为了解决上述问题,就需要用Comparable接口了。实现Comparable接口后,就得重写compareTo方法。

package Blog;import java.util.Arrays;class Student implements Comparable<Student> {public int score;public String name;public Student() {}public Student(int score, String name) {this.score = score;this.name = name;}@Overridepublic String toString() {return "Student{" +"score=" + score +", name='" + name + '\'' +'}';}@Overridepublic int compareTo(Student o) {return this.score - o.score;}
}
public class test {public static void main(String[] args) {Student student1 = new Student(90, "张三");Student student2 = new Student(80, "王三");Student student3 = new Student(70, "李三");Student student4 = new Student(40, "高三");Student student5 = new Student(50, "马三");Student[] students = {student1, student2, student3, student4, student5};Arrays.sort(students);System.out.println(Arrays.toString(students));}
}

上面的代码中,实现Comparable接口后,需要指定一个类型,这个类型就是我们要比较的类型。

主要还得看compareTo方法,这个方法中,定义了比较规则,规则就是如果前一个对象的score比后一个对象的score大,那么就返回一个正数,如果两个对象的score相等,就返回一个0,如果后一个对象的score比前一个对象的score大,就返回一个负数,编译器正是利用这个规则来进行排序的。就是说我们目前的代码就是以根据每个对象的score来进行排序的。

 如果是想要以score为基准,从大到小排序,只需要把compareTo中的this和o调换位置即可。

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

如果要是基于name字段进行排序。就需要把重新在compareTo中实现。

 public int compareTo(Student o) {return this.name.compareTo(o.name);}

可以看出在compareTo中再次的调用了compareTo方法,但是需要注意的是,这个compareTo方法不是我们写的这个方法,而是String的compareTo方法。因为name是String类型的。

以下代码就是String类的compareTo方法。

public int compareTo(String anotherString) {int len1 = value.length;int len2 = anotherString.value.length;int lim = Math.min(len1, len2);char v1[] = value;char v2[] = anotherString.value;int k = 0;while (k < lim) {char c1 = v1[k];char c2 = v2[k];if (c1 != c2) {return c1 - c2;}k++;}return len1 - len2;}

以字典序进行比较,如果前一个的name在字典序中大于后一个的name,那么就返回一个正数,如果前一个的name在字典序中比后一个的name在字典序中小,就返回负数。如果两个name都遍历完之后,还是没有发现不一样的字符,就返回他们的长度差值。

可以看出,当我们重行在compareTo中定义规则之后,排序的时候,就会按照我们定义的规则进行排序。 

如果此时Student类中有很多的字段,当我们业务变化的时候,就得更改把compareTo的比较规则。

Comparator接口

    @Overridepublic int compare(Student o1, Student o2) {return 0;}

compare方法是有两个参数的,所以基于Comparator接口自定义一个比较器。

package Blog;import java.util.Arrays;
import java.util.Comparator;class Student {public int score;public String name;public Student() {}public Student(int score, String name) {this.score = score;this.name = name;}@Overridepublic String toString() {return "Student{" +"score=" + score +", name='" + name + '\'' +'}';}
}/*** 基于score的比较器*/
class ScoreComparator implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return o1.score - o2.score;}
}/*** 基于name的比较器*/
class NameComparator implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return o1.name.compareTo(o2.name);}
}public class test {public static void main(String[] args) {Student student1 = new Student(90, "abc");Student student2 = new Student(80, "bdc");ScoreComparator scoreComparator = new ScoreComparator();  //实例化基于score比较器//通过score比较器来比较两个对象的大小System.out.println(scoreComparator.compare(student1,student2));NameComparator nameComparator = new NameComparator();  //实例化基于name的比较器//通过name比较器来比较两个对象的大小System.out.println(nameComparator.compare(student1,student2));}
}

可以看出还是和Comparable的compareTo方法的返回值一样。

我们通过自定义比较强的方式来定义对象的比较规则。

当前Student对象有两个属性,我们也就定义了两个比较规则,如果有多个属性的话,我们也可以定义多个比较规则,当我们想用那个属性进行比较的时候,就实例化对应属性的比较器,来进行比较。

我们常用到的Arrays.sort();方法也可以在在指定参数的时候,把我们写的比较器传入过去,在排序的时候就会以我们的传入的比较器的比较规则来进行排序。

package Blog;import java.util.Arrays;
import java.util.Comparator;class Student {public int score;public String name;public Student() {}public Student(int score, String name) {this.score = score;this.name = name;}@Overridepublic String toString() {return "Student{" +"score=" + score +", name='" + name + '\'' +'}';}
}/*** 基于score的比较器*/
class ScoreComparator implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return o1.score - o2.score;}
}/*** 基于name的比较器*/
class NameComparator implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return o1.name.compareTo(o2.name);}
}public class test {public static void main(String[] args) {Student student1 = new Student(90, "abc");Student student2 = new Student(80, "bdc");ScoreComparator scoreComparator = new ScoreComparator();  //实例化基于score比较器//通过score比较器来比较两个对象的大小System.out.println(scoreComparator.compare(student1,student2));NameComparator nameComparator = new NameComparator();  //实例化基于name的比较器//通过name比较器来比较两个对象的大小System.out.println(nameComparator.compare(student1,student2));Student[] students ={student1,student2};Arrays.sort(students,scoreComparator);   //同时传入我们自定义的score比较器,排序时会以比较器的规则来排序System.out.println(Arrays.toString(students));Arrays.sort(students,nameComparator);//同时传入我们自定义的name比较器,排序时会以比较器的规则来排序System.out.println(Arrays.toString(students));}
}

第一个输出是以score的比较器来进行排序的。

第二个输出是以name的比较器来进行排序的。 


http://chatgpt.dhexx.cn/article/y2pp6ptj.shtml

相关文章

Java Comparator的使用

这是啥&#xff1f; Comparator是个接口&#xff0c;是一个比较器&#xff0c;常用内部类的方式实现&#xff0c;常用于实现某个类的比较规则 怎么用&#xff1f; 场景&#xff1a;假如有一个字符串集合list&#xff0c;一共有10个元素&#xff0c;乱序的。现有排序规则orde…

Comparable与Comparator浅析

欢迎支持笔者新作&#xff1a;《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》&#xff0c;同时欢迎关注笔者的微信公众号&#xff1a;朱小厮的博客。 欢迎跳转到本文的原文链接&#xff1a;https://honeypps.com/java/comparable-and-comparator-analysis/ 今天…

Comparator和Comparable的区别

一、概述 Comparable和Comparator都是两个接口&#xff0c;接口都可以用来实现集合中元素的比较、排序&#xff0c;Comparator位于包java.util下&#xff0c;而Comparable位于包java.lang下&#xff0c;Comparable接口将比较代码嵌入自身类中&#xff0c;而Comparator既可以嵌入…

Comparator使用简介

1、Lambda表达式 2、Comparator使用简介 文章目录 一、使用方式1、Stream中sorted()方法2、Stream中max()方法3、Stream中排序JSONObject方法 二、具体方法1、 compare2、 equals3、 naturalOrder4、 comparing5、 comparingInt6、 comparingLong7、 comparingDouble8、 nullsF…

Comparator详解

前面我们讲过Java提供了一个用于比较的接口Comparable,提供了一个比较的方法,所有实现该接口的类,都动态的实现了该比较方法。实际上Java中除了比较一个接口外&#xff0c;还提供了一个接口&#xff0c;该接口也是具有比较的功能&#xff0c;但该接口注重的却是比较容器&#x…

Hough变换的理解

Hough变换&#xff1a; 原理&#xff1a;将一个空间映射到另一个空间。这里是将X&#xff0c;Y空间映射到R,Φ空间。看下图&#xff1a;左图是X,Y空间的直线&#xff0c;该直线方程&#xff1a;ykx b&#xff0c;确定方程的参数k,b也可以组成一个空间&#xff0c;这个空间中的…

matlab hough变换检测平行直线,浅谈Hough变换的平行直线检测改进方案

在遥感图像中,对江河上桥梁目标的识别具有重要意义。由于桥梁的最突出特征在于桥体的平行直线,所以对平行直线的实时检测十分重要。经典的Hough变换是一种常用的检测直线的方法,Hough变换的研究及应用动态:Hough变换于1962年由Paul Hough提出,并在美国作为专利被发表。它所…

Hough变换检测直线与圆的原理

霍夫变换的基本原理 霍夫变换(Hough Transform)可以理解为图像处理中的一种特征提取技术&#xff0c;通过投票算法检测具有特定形状的物体。霍夫变换运用两个坐标空间之间的变换将在一个空间中具有相同形状的曲线或直线映射到另一个坐标空间中的一个点形成峰值&#xff0c;从而…

Hough变换圆检测定位

Hough变换基本原理 Hough变换是由Paul Hough于1962年提出的一种检测圆的算法&#xff0c;它的基本思想是将图像从原图像空间变换到参数空间&#xff0c;在参数空间中&#xff0c;使用大多数边界点都满足的某种参数形式作为图像中的曲线的描述&#xff0c;它通过设置累加器对参…

【图像处理——hough变换那些事】

#老板的每一次点赞&#xff0c;都是对小编精神上的支持&#xff0c;愿各位老板一路长虹&#xff0c;学习进步。 点赞点赞&#xff01;&#xff01;&#xff01;&#xff01; #author&#xff1a;yyt time:2023.5.5 #机器学习—图像处理 #本文为小编第一次写文章&#…

基于Hough变换的直线检测(Matlab)

点击上方“3D视觉工坊”&#xff0c;选择“星标” 干货第一时间送达 作者丨无敌三脚猫 来源丨 古月居 1、引言 该程序实现了一些基本的图像处理算法&#xff0c;并将它们组合在一起&#xff0c;构建了一个基于霍夫变换的直线检测器。该程序能够在图像中找到直线段的起始点和结束…

Hough变换原理

霍夫变换在识别方程式已知的曲线是常用的一种方法&#xff0c;本文通过识别直线方程为向导&#xff0c;说明霍夫变换的原理。 话不多说&#xff0c;开始今天的主题&#xff0c;我们处理的对象是二值黑白图像&#xff0c;如下图&#xff1a; 上图是我自绘的五个点&#xff0c;考…

图像处理算法 之 Hough变换

Hough变换 一、标准Hough线变换(SHT)1.1 原理1.2 SHT步骤1.3 缺点 二、渐进概率Hough变换(PPHT)2.1 原理及步骤2.2 缺点 三、Hough圆变换3.1 原理及步骤3.2 缺点 四、实验代码 一、标准Hough线变换(SHT) 1.1 原理 标准Hough变换&#xff08;standard hough transform&#xf…

MATLAB中的Hough变换

下面来介绍一下关于Hough变换的原理及其如何在MATLAB中实现。 Hough变换&#xff1a;Hough变换是一种使用表决原理的参数估计技术。其原理是利用图像空间和Hough参数空间的点&#xff0d;线对偶性&#xff0c;把图像空间中的检测问题转换到参数空间。国内外对Hough变换的研究及…

智能图像分析——Hough变换

一、原理 引用 hough变换利用点、线对偶的思想&#xff0c;把提取图像空间中直线的问题转换成在参数空间/hough空间中计算点的峰值的问题。 在x − y坐标系中&#xff0c;假设有一条直线过点( x0 , y0 )&#xff0c;那么我们可以把这条直线的方程记为 ymxb&#xff08;1&#…

霍夫Hough变换

参考: https://blog.csdn.net/qq_15971883/article/details/80583364 MATLAB帮助文档 Hough变换是一种使用表决方式的参数估计技术,其原理是利用图像空间和Hough参数空间的线-点对偶性,把图像空间中的检测问题转换到参数空间中进行。 利用Hough变换检测直线 记住:直角坐标…

Hough变换及MATLAB示例

前言 在车道线检测中&#xff0c;最小二乘法&#xff0c;Hough变换是车道线模型拟合的传统方法之一&#xff0c;通过一系列离散的点拟合出车道直线&#xff0c;也就是得到基于像素平面坐标系的左车道和右车道直线方程。 Hough变换 Hough变换的基本思想 我们先来看看如何表达…

hough变换算法

VoteNet网络中会用Deep Hough Voting&#xff0c;所以先来学习一下Hough Voting。 正文开始 hough变换算法 1、算法思想 霍夫变换于1962年由Paul Hough 首次提出&#xff0c;后于1972年由Richard Duda和Peter Hart推广使用&#xff0c;经典霍夫变换用来检测图像中的直线&…

Hough 变换

Hough 变换是图像处理中&#xff0c;检测直线最基本&#xff0c;也是应用最广泛的一种传统方法。虽然现在是深度学习大行其道的时代&#xff0c;但是很多传统的算法&#xff0c;依然有其参考的价值所在&#xff0c;至少从数学表达上来看&#xff0c;是更加的简洁&#xff0c;有…

Hough transform(霍夫变换)

主要内容&#xff1a; 1、Hough变换的算法思想 2、直线检测 3、圆、椭圆检测 4、程序实现 一、Hough变换简介 Hough变换是图像处理中从图像中识别几何形状的基本方法之一。Hough变换的基本原理在于利用点与线的对偶性&#xff0c;将原始图像空间的给定的曲线通过曲线表达形式变…