Java比较器:Comparable和Comparator

Mission Planner连接Autopilot保姆级教程:从USB到无线全搞定 本文提供Mission Planner连接Autopilot的全面指南,涵盖USB直连、无线数传、蓝牙适配等多种连接方案。详细讲解驱动安装、波特率匹配、性能优化等关键步骤,并分享多链路冗余配置与故障转移的高阶技巧,助你快速解决连接问题。 阅读详情

1、是什么

Comparable和Comparator都只是一个普通的接口。他们是Java用来定义如何比较两个对象大小的规范,真正的比较逻辑需要由实现类来重写其中的比较方法。

2、为什么

在Java中,两个数值类型的变量可以使用比较运算符(">","<"等)直接比较两个数值的大小,但是对于引用类型的数据,则不能直接通过比较运算符(">","<"等)来比较两个对象的大小。所以,Java另外提供了两种用来比较两个对象大小的方式:Comparable和Comparator。

3、怎么用

(1)Comparable(自然排序)

java.lang.Comparable 需要子类来实现该接口,并重写当中的compareTo(Object obj)方法,一旦定义完成后就可以在任何地方对该类的对象进行比较排序(可以认为是在对象内部排序)。

直接看Comparable的源码,里面只定义了一个抽象方法 compareTo(Object obj)。

package java.lang;

public interface Comparable<T> {

    int compareTo(T var1);
}

对于任何一个类,只要实现了 java.lang.Comparable 中的compareTo() 方法,该类的对象就可以使用定义的方式进行比较。Java中的包装类和String类都实现了该接口。下面以 java.lang.String 类为例:

@Test
public void test01() {
    List<String> list = Arrays.asList("FF", "AA", "BB", "DD", "TT");
    System.out.println("before:" + list);
    //实现Comparable接口的对象列表(和数组)可以通过 Collections.sort 或 Arrays.sort进行自动排序。
    //实现此接口的对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。
    Collections.sort(list);
    System.out.println("after:" + list);
}

输出结果:
before:[FF, AA, BB, DD, TT]
after:[AA, BB, DD, FF, TT]

查看String源码可以看到,String类实现了Comparable接口,并且重写了compareTo() 方法,所以可以直接使用Collections.sort()方法进行排序,当两个String对象进行比较时,底层实际是通过从前往后比较每个char字符的Unicode值大小。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
        
      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;
    } 
   // ...其他代码省略
}

接着,我们再来自己定义一个Person类来进一步说明:

public class Person implements Comparable<Person> {

    String name;
    int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

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

    /**
     * 要求:先按照age从小到大,age相同时,再按照name从大到小排序
     *
     * @param p 和 this对象进行比较的对象
     * @return
     * 返回1:  this大于p
     * 返回0:  this等于p
     * 返回-1: this小于p
     */
    @Override
    public int compareTo(Person p) {
        if (this.age != p.age) {
            return Integer.compare(this.age, p.age);
        } else {
            //注意这里加 “-”号
            return -this.name.compareTo(p.name);
        }
    }

}

下面进行测试:

@Test
public void test02() {
    List<Person> list = new ArrayList<>();
    list.add(new Person("aa", 20));
    list.add(new Person("cc", 12));
    list.add(new Person("bb", 17));
    list.add(new Person("dd", 18));
    list.add(new Person("ee", 18));

    System.out.println("before:" + list);
    Collections.sort(list);
    System.out.println("after:" + list);
}

输出结果:
before:[Person{name='aa', age=20}, Person{name='cc', age=12}, Person{name='bb', age=17}, Person{name='dd', age=18}, Person{name='ee', age=18}]
after:[Person{name='cc', age=12}, Person{name='bb', age=17}, Person{name='ee', age=18}, Person{name='dd', age=18}, Person{name='aa', age=20}]

但是,实现Comparable的方式也有一些局限性,对于一些特殊场合,如果不想使用原来类中定义的比较方式,而是想使用其他比较方式,又或者想用于比较的对象是第三方库的类,不能进行修改的情况,实现Comparable的方式就不太适合了,这时就可以使用Java提供的第二种排序方式:Comparator。

(2)Comparator(定制排序)

java.util.Comparator 字面意思是比较器,是用来对两个对象进行比较的工具(可以认为是在对象外部排序)。

/**
 * 要求:使用定制排序:先按照name从小到大,name相同时,再按照age从大到小排序
 */
@Test
public void test04() {
    List<Person> list = new ArrayList<>();
    list.add(new Person("aa", 20));
    list.add(new Person("cc", 12));
    list.add(new Person("bb", 17));
    list.add(new Person("ee", 18));
    list.add(new Person("dd", 18));

    System.out.println("before:" + list);
    //因为只使用一次,所以可以使用匿名内部类的方式
    Collections.sort(list, new Comparator<Person>() {
        @Override
        public int compare(Person o1, Person o2) {
            //这里就没有判空了
            if (!o1.name.equals(o2.name)) {
                return o1.name.compareTo(o2.name);
            } else {
                //名字相同就比较年龄,注意这里要加“-”号
                return -Integer.compare(o1.age, o2.age);
            }
        }
    });
    System.out.println("after:" + list);
}

输出结果:
before:[Person{name='aa', age=20}, Person{name='cc', age=12}, Person{name='bb', age=17}, Person{name='ee', age=18}, Person{name='dd', age=18}]
after:[Person{name='aa', age=20}, Person{name='bb', age=17}, Person{name='cc', age=12}, Person{name='dd', age=18}, Person{name='ee', age=18}]

(3)两种方式对比总结:

(1)从名称中可以看出,Comparable以“able”结尾,意思是“可xxx的”,java中也有很多其他类似命令的类,如:Cloneable等。他们的意思基本都是用来定义一种规范或声明,具体的实现细节由实现类来完成。而Comparator是以“or”结尾,一般指的是该类是一个工具型的类。类似的也有:Executor等。

(2)当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码, 或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那 么可以考虑使用 Comparator 的对象来排序

(3)a. 重写compareTo(Object obj)方法时:

  • 如果当前对象this大于形参obj,则返回正整数;
  • 如果当前对象this等于形参obj,则返回0;
  • 如果当前对象this小于形参obj,则返回负整数。

         b. 重写compare(Object o1,Object o2)方法:

  • 如果o1大于o2,则返回正整数;
  • 如果 o1等于o2,则返回0;
  • 如果 o1小于o2,则返回负整数。

         记忆方法:可以认为:返回数的值 = 前面对象 - 后面对象。

(4)Java中的包装类和String都实现了Comparable接口,重写了compareTo(Object obj)方法,实现了比较两个对象大小的方式。其中:

  • String:按照字符串中每个字符的Unicode编码值进行比较;
  • Character:按照字符的Unicode编码值进行比较;
  • Integer、Long、Float、Double、Byte等数值类型对应的包装类:按照他们对应的数值大小进行比较
  • Boolean:true对应的包装类实例 > false对应的包装类实例;
  • Date、Time等日期时间类:后面的日期大于前面的日期大小(实际比较的是它们对应的时间戳大小)。

(5)实现了Comparable接口的类或者使用调用带Comparator实现类的方式,都可以使用java中的Arrays.sort()方法,或者Collections.sort()方法对多个对象进行排序,Collections.sort() 底层其实也是使用的Arrays.sort(),底层实际就是使用对象实现的compareTo(Object obj)或compare(Object o1, Object o2)方法对数组或集合进行排序。可以参考另一篇文章:https://blog.youkuaiyun.com/u011410529/article/details/56668545

(6)由于 null 不是一个类,也不是一个对象,因此在重写 compareTo 方法时应该注意 e.compareTo(null) 的情况,即使 e.equals(null) 返回 false,compareTo 方法也应该主动抛出一个空指针异常 NullPointerException。

(7)Comparable 实现类重写 compareTo 方法时一般要求 e1.compareTo(e2) == 0 的结果要和 e1.equals(e2) 一致。这样将来使用 SortedSet 等根据类的自然排序进行排序的集合容器时可以保证保存的数据的顺序和想象中一致。

 

参考地址:

Java 解惑:Comparable 和 Comparator 的区别:https://zhuanlan.zhihu.com/p/24081048

Arrays.sort和Collections.sort实现原理解析:https://blog.youkuaiyun.com/u011410529/article/details/56668545

推荐文章:

剖析JDK8中Arrays.sort底层原理及其排序算法的选择:https://www.jianshu.com/p/d7ba7d919b80

多周期路径约束(set_multicycle_path ) 1.由慢到快的多周期约束 如下图所示,发射时钟周期是接受时钟周期的4倍。默认情况下,按照1T原则来进行静态时序分析和布局布线的。即建立时间是在发射沿后的第一个捕获沿检查,而保持时间是同一时刻下源时钟和捕获时钟的触发边沿下检查的(建立时间检查边沿的前一个触发沿)。 但是这样导致的问题就是该路径过于苛刻,为了满足这条路径的要求,不得不放弃其他路径。或者根本没办法保证这个默认的约束。总之最终造成... 阅读详情

相关推荐

QMT量化交易桥接方案深度对比:从MiniQMT淘汰说起

量化交易系统中的API桥接,本质是解决本地终端与底层交易引擎之间的通信瓶颈。其核心原理在于绕过GUI封装、直连确定性执行层,从而获得低延迟、高可靠、可监控的指令通路。技术价值体现在策略实盘一致性提升、毫秒级响应保障及运维可控性增强。典型应用场景包括打板策略、T+0套利、高频网格等对时效与稳定性双敏感的自动化交易。本文聚焦国金证券QMT专业版生态,系统剖析DLL注入、HTTP反向代理、IPC共享内存与官方HTTP API四大桥接路径的性能边界、合规风险与工程落地成本,尤其深入解析qmt终端 client is

weixin_33892359的博客 457

java比较器(comparable)

目录标题一、comparable二、Comparator(自定义比较器) 一、comparable 用于比较对象的大小,像String、包装类等实现了Comparable接口,重写了compareTo()方法,给出了比较两个对象大小。 package compare; import java.util.Arrays; /* * java比较器 * */ public class CompareTest { public static void main(String[] args) {

a123123sdf的博客 927

ANSYS CFX 自定义函数数据导入实战指南

本文详细介绍了在ANSYS CFX中实现自定义函数数据导入的完整流程与实战技巧。通过具体案例,指导用户如何将外部实验或计算数据(如材料属性随温度变化)导入CFX,创建可调用的函数,并正确关联到仿真模型中,从而显著提升仿真的真实性与准确性。

v6b7n8m9q0的博客 702

【Java】比较器(comparator,comparable 的使用)

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

摸鱼小小虫的博客 2171

SCL3400-D01双轴高精度倾角计

简介 两轴高精度加速度计,提供两个模式。 ±30° with 10 Hz LPF ±90° with 40 Hz LPF Resolution up to 32768 LSB/g Ultra-low 0.0009°/√Hz noise density 这款传感器是替换之前村田的停产的模拟量系列的芯片,正在测试中,具体效果大伙可以评测。 一、引脚连接图 引脚图兼容SCL3300 二、SPI接口 1.SCL3300和SCL3400略有区别如下图 左边为SCL3...

专注惯导领域 3808

Claude Code+Cursor+Claude 4三剑合璧!5步搞定Magentic-UI的OAuth2.0集成,开发效率飙升500%,新手秒变全栈工程师

本文详细介绍了如何利用Claude Code、Cursor和Claude 4三款AI工具高效集成Magentic-UI的OAuth2.0认证系统。通过5个步骤的实战演练,开发者可快速完成从环境搭建、项目分析、代码生成到前端集成的全过程,显著提升开发效率。文章还提供了JWT令牌管理、安全配置及常见问题解决方案。

weixin_29234509的博客 453

java中compareTo比较两个日期大小

java中compareTo比较两个日期大小我们对两个日期进行比较的时候,或者是日期的string进行比较的时候,以前我一直以为,如果大于的话compareTo的返回值应该是1,等于的话是0,小于的话是-1,网上很多也是这样说,但是现实中我程序出错,最后打出来,看了一下,如果大于的话返回的是正整数,等于是0,小于的话就是负整数,而不仅仅局限于1,0和-1,以后做比较要注意(这段话出处见此)小例子如下

baifq的记录博客 13万+

3D iToF深度分辨率测量

本文展示了RGB-D传感器在三维测量中的高精度表现。标靶深度图显示其具备清晰、低噪、无干扰的特性,点云数据完整度高且轮廓分明。该技术已成功应用于物流(体积测量误差<1%)、工业(高反光部件装配检测)和农业(果蔬成熟度分级)等领域,验证了其硬件和算法的可靠性,能够满足不同场景下的三维测量需求。

dream it possible 252

DateTime.Compare(t1,t2)比较两个日期大小

DateTime.Compare(t1,t2)比较两个日期大小,排前面的小,排在后面的大,比如:2011-2-1就小于2012-3-2 返回值小于零:  t1 小于 t2。  返回值等于零 : t1 等于 t2。  返回值大于零:  t1 大于 t2。  using System; using System.Collections.Generic; using System.L

kone666 4529

手把手教你使用ConvNeXt训练自己数据集和推理,ConvNeXt模型训练(CVPR 2022),一个能挑战 Vision Transformer 的卷积神经网络,含完整代码和数据集

手把手教你使用ConvNeXt训练自己数据集和推理,ConvNeXt模型训练(CVPR 2022),一个能挑战 Vision Transformer 的卷积神经网络,含完整代码和数据集

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 1449

深入YOLOv8内部核心:用RepNCSPELAN4深度重构主干网络,即插即用的高效涨点方案

本文提出了一种改进YOLOv8目标检测模型的方法,通过在YOLOv8中引入RepNCSPELAN模块来提高检测性能。该模块融合了RepVGG重参数化思想与CSP-ELAN结构,在保持推理速度的同时增强特征表达能力。实验结果表明,改进后的RepNCSPELAN-YOLOv8相比原模型在多项指标上均有提升:准确率从0.84提高到0.86,召回率从0.72提升至0.81,mAP50和mAP50-95也分别提高了0.06和0.04。文章详细介绍了模块设计原理和移植步骤,包括配置文件创建、代码修改等关键环节,为YOL

FJN110的博客 186

Java的两种比较器用法:Comparable和Comparator

    Java有两种比较器:Comparable和Comparator。Comparable称之为内部比较器,实体类实现该接口,重写compareTo方法; Comparator称之为外部比较器,可以自定义比较器类,实现该接口,重写compare方法。Comparator使用起来比Comparable更加的灵活,方便。以下是两种比较器具体的使用实例: 1、内部比较器Comparable示例 ...

weixin_42315600的博客 950

【小白CV教程】YOLOv5+Deepsort实现车辆行人的检测、追踪和计数

【小白CV教程】YOLOv5+Deepsort实现车辆行人的检测、追踪和计数本文禁止转载!项目简介:YOLOv5检测器:DeepSort追踪器:运行demo:训练自己的模型:调用接口:创建检测器:调用检测接口: 本文禁止转载! 项目简介: 使用YOLOv5+Deepsort实现车辆行人追踪和计数,代码封装成一个Detector类,更容易嵌入到自己的项目中。 代码地址(欢迎star): https://github.com/Sharpiless/Yolov5-deepsort-inference 最终效果:

梁瑛平的博客 5万+

JAVA自定义比较器Comparator 和 Comparable

JAVA有两种比较器,分别是:Comparator 和 Comparable 我看网上说Comporable是内部比较器,而Comparator是外部比较器,由于这两个都是接口,所以都需要去实现,而实现Comporable接口则需要实现compareTo方法,实现Comparator需要实现compare方法。Comparable接口一般由要比较的类实现,所以叫内部比较器,而comparator比...

dream_follower的博客 1548

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Java的比较器 Comparable 和 Comparator

在 Java 中,Comparable 和 Comparator 是用于对象排序的重要接口。它们提供了不同的排序方式,适用于不同的需求,同时在 Java 底层排序算法中发挥着关键作用。本文将从基础概念、使用方法、排序实现(包括升序、降序)、底层实现原理以及适用场景等方面进行详细解析。

weixin_73144915的博客 1883

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

【Java SE】Java比较器:Comparable、Comparator

Java中的对象,正常情况下,只能进行比较:==或!。不能使用或。但是在实际开发场景中,有时候需要对多个对象进行排序,言外之意,就是需要比较对象的大小。这便引出了两个接口。

m0_55908255的博客 1542

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

java 比较器 返回值_Java的比较器Comparable与Comparator

在Java中有两个比较器:Comparable、Comparator对于Integer、Double等等类型,可以直接对他们进行比较,因为已经实现了比较的方式,然而在平时常常会面临需要对集合进行排序的情况,这种情况下我们需要人工定义Java比较器,告诉程序两个对象如何比较大小。ComparableComparable称为内部比较器,因为我们创建需要排序的类还要实现这个类,在创建之初就要人工规定好了...

weixin_29767975的博客 1550

Java 比较器Comparable和Comparator的使用和区别

1、Comparable和Comparator介绍 在java中Intege,Double等基本数据类型和Sting都实现了Comparable接口,不用我们在自己去实现。对于类的比较,需要我们定义比较用到的字段比较逻辑。Comparable是内部比较器需要在类内部实现,Comparator是外部比较器生成比较器对象。 2、使用 (1)类实现Comparable接口重写comp...

old_land的博客 495

JAVA中,Comparator 和 Comparable 比较器

1.Comparable是排序接口;若一个类实现了Comparable接口,就意味着“该类支持排序”。 (作用在实体类上) 编写实体类 //实现Comparable接口,泛型为House类 public class House implements Comparable<House> { private double area;//面积 private double money;//房价 //重写Comparable的方法 @Override public i

风口浪尖的博客 513

java基础之比较器(comparable和Comparator)

1.比较器的两种方式: 内部比较器 外部比较器 2.内部比较器:定义在要比较的类中,通过comparable接口进行实现 。 1)定义一个Person类,具有name和age属性。 2)implements Comparable接口,并重写compareTo方法 3)实现compareTo方法的内部逻辑。 4)写一个测试类。将Person对象添加到TreeSet中,看是否实现排序。 ...

醒醒 554

Java 两个比较器 Comparable 和 Comparator 的区别

1 前言 在我们自定义的数据结构需要排序时,需要一定的排序规则,这就需要用到今天我们介绍的两个比较器 Comparable 和 Comparator。 2 Comparable Comparable 位于 java.lang 包下,本质上是一个内比较器,实现了 Comparable 的类可以自己比较,至于比较的结果如何则需要依赖于自然比较方法 compareTo 的实现。 compareTo 的返...

Geffin的博客 607

java 比较器comparator_Java中的比较器Comparable、Comparator

在Java代码中,我们常常会面临需要对集合进行排序的情况,这种情况下我们需要手动的定义Java比较器,告诉程序两个对象如何比较大小。Java中的比较器分为两种Comparable和Comparator:Comparable:实现Comparable接口,并且重写compareTo(T o)方法Comparator:实现Comparator接口,并且重写compare()和equals()方法Com...

weixin_42311115的博客 204

Java 函数接口Comparator和Comparable【比较器接口】详解与示例

通常要对数据进行排序,数据对象的类需要实现 Comparable 接口。有的情形需要在不修改类本身的情况下定义多种排序规则,则可以使用 Comparator 接口。所以这两种接口均用于排序,但使用方式略有不同。Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。 当一个类的自然比较顺序是固定的,使用 Comparable 是一个好的选择。例如,对于一些基本数据类型的包装类(如 Integer、Double 等),它们都实现了 Comparable 接口,具有自然的比较顺序。

weixin_42369079的博客 1674

java中Comparable和Comparator的用法和区别 Comparable自然排序 Comparator比较器排序

java中Comparable和Comparator的用法和区别 Comparable自然排序 Comparator比较器排序 一、概述 Comparable和Comparator在java中都是用于来比较数据大小。实现Comparable接口需要重写compareTo方法,实现Comparator方法需要重写compare方法。 这两个方法返回值都是int类型,根据返回值来判断比较对象...

HaHa_Sir的博客 2500

JAVA中Comparable和Comparator两类比较器

Comparable 是排序接口

WHS-_-2022的博客 341

java比较器Comparator 和 Comparable

一.比较器 Comparator 和 Comparable 比较: 1.Comparable是排序接口;若一个类实现了Comparable接口,就意味着“该类支持排序”。(作用在实体类上) 2.而Comparator是比较器;我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。(作用在排序类上) 总结:Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。 案例:使用两种不同的比较器分别对5本书进行排序,书的属性有:书名,作者,价格。要求使用内部比

xing_yu_xianko的博客 173
上一篇: 谈谈Java中最常用的类—String
下一篇: 深入理解JDBC
ProgrammingWay
博客等级 码龄9年 58粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值