Java比较器(comparable) (comparator)

2024-04-02 17:20

本文主要是介绍Java比较器(comparable) (comparator),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.前言

我们经常使用>,<,=等运算符来比较数与数之间的大小关系,但显然这些运算符并不同样适用于对象.但如果需要比较对象,那么我们应该怎么办呢?

我们可以考虑两种方法 : (1) 自然排序 (2). 定制排序.

2.自然排序(实现Comparable接口)

(1). 为什么String类的对象可以进行比较大小,正是因为String类实现了Comparable接口,并重写了comparaTo(Object o)方法.

(2). 操作步骤

  • 设计类实现Comparable接口
  • 重写compareTo(Object o)方法.在此方法中指明对象比较的标准.
  • 创建类的多个实例,调用Arrays.sort()方法比较.

(3). 例 : 

public class Phone implements Comparable{private String name;private double price;public Phone() {}public Phone(String name, int price) {this.name = name;this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getPrice() {return price;}public void setPrice(int price) {this.price = price;}@Overridepublic int compareTo(Object o) {if (this == o) {return 0;}if (o instanceof Phone) {Phone p = (Phone) o;return Double.compare(this.price, p.price);}throw new RuntimeException();}@Overridepublic String toString() {return "Phone{" +"name='" + name + '\'' +", price=" + price +'}';}
}public class PhhoneTest {public static void main(String[] args) {Phone[] p1 = new Phone[5];p1[0] = new Phone("xiaomi", 4900);p1[1] = new Phone("vivo", 5900);p1[2] = new Phone("oppo", 6900);p1[3] = new Phone("huawei", 7900);p1[4] = new Phone("iPhone", 8900);Arrays.sort(p1);for (int i = 0; i < p1.length; i++) {System.out.println(p1[i].toString());}}
}控制台
Phone{name='xiaomi', price=4900.0}
Phone{name='vivo', price=5900.0}
Phone{name='oppo', price=6900.0}
Phone{name='huawei', price=7900.0}
Phone{name='iPhone', price=8900.0}

上面代码实现了price为标准实现了对象之间的比较.如果我们需要以name为标准我们应该怎么办呢?

只需要修改具体类(Phone)中重写的compareTo(Object o)方法.

@Overridepublic int compareTo(Object o) {if (this == o) {return 0;}if (o instanceof Phone) {Phone p2 = (Phone) o;return p1.getName().compareTo(p2.getName());}throw new RuntimeException();}控制台
Phone{name='huawei', price=7900.0}
Phone{name='iPhone', price=8900.0}
Phone{name='oppo', price=6900.0}
Phone{name='vivo', price=5900.0}
Phone{name='xiaomi', price=4900.0}

return语句中调用了String类重写的compareTo(Object o)方法.比较字符串对象大小.如果左边字符串比右边的小,返回负数.如果左边的比右边的大,返回正数.如果相等,返回0.上文Double.compare(double a,double b)方法同理.

3.定制排序(实现Comparator接口)

(1). 思考

  • 当元素所属的类没有实现java.lang.Comparable接口并且不方便修改时.
  • 如果一个类实现了Comparable接口,也指定了两个对象的比较规则,但我们不想按照它预定义的方式去比较对象,而且我们不能随意修改,那我们应该怎么办呢?
  • 如String[] s =new String[10];//静态初始化;Arrays.sort(s)是将字符串从小到大排序完毕,但我们期望将字符串从大到小排序,但我们不能随意修改String类中的源码,我们应该怎么办呢?

(2). 我们可以增加java.util.Comparator接口,强制按照我们想要的方式去比较对象.

  • 重写Conpare(Object o1, Object o2)方法,比较二者的大小.
  • 将Comparator接口的实现类的对象作为参数传入到sort方法中,从而允许以自己想要的方式进行排序.

(3). 例 : 以字符串为比较的依据进行对象的比较.此处使用匿名实现类的匿名对象更为方便.如果想以price作为比较的依据,只需改动Compare(Object o1, Object o2)方法即可.

public class PhhoneTest {public static void main(String[] args) {Phone[] p1 = new Phone[5];p1[0] = new Phone("xiaomi", 4900);p1[1] = new Phone("vivo", 5900);p1[2] = new Phone("oppo", 6900);p1[3] = new Phone("huawei", 7900);p1[4] = new Phone("iPhone", 8900);Arrays.sort(p1, new Comparator<Phone>() {@Overridepublic int compare(Phone o1, Phone o2) {if (o1 == o2) {return 0;}if (o1 instanceof Phone && o2 instanceof Phone) {Phone a = (Phone) o1;Phone b = (Phone) o1;return a.getName().compareTo(b.getName());}throw new RuntimeException();}});for (int i = 0; i < p1.length; i++) {System.out.println(p1[i].toString());}}
}

4.两种方式的比较

(1).

自然排序比较单一,唯一.

定制排序比较灵活,多样.

(2).

自然排序是一劳永逸的.

定制排序是临时的.

(3).

自然排序对应的接口类型是Comparable,重写的是CompareTo(Object o)方法.

定制排序对应的接口类型是Comparator,重写的是Compare(Object o1, Object o2)方法

注意到为什么CompareTo方法的形参有一个,而Compare方法有两个.

很简单,因为this对象(该方法的调用者)跟传入方法的对象的类型相同,都是具体类(如上的Phone),而compareTo方法的this跟具体类的对象并无关系,充当传入sort方法的参数,所以将两个需要比较的对象都传入到Compare方法中.

这篇关于Java比较器(comparable) (comparator)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/870593

相关文章

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Spring AI集成DeepSeek的详细步骤

《SpringAI集成DeepSeek的详细步骤》DeepSeek作为一款卓越的国产AI模型,越来越多的公司考虑在自己的应用中集成,对于Java应用来说,我们可以借助SpringAI集成DeepSe... 目录DeepSeek 介绍Spring AI 是什么?1、环境准备2、构建项目2.1、pom依赖2.2