当前位置: 首页 > news >正文

Java(十二)——Comparable接口与Comparator接口

文章目录

  • Comparable与Comparator接口
    • Comparable接口
    • Comparator接口

Comparable与Comparator接口

我们可能会遇到这样的问题:怎么对一个对象数组进行排序? 比如对一个狗类对象数组进行排序,而想到这,我们又会有一个问题:怎么比较两个对象?如果我想自定义标准,怎么办?

与基本类型的比较并排序不同,对象数组没有一个统一的标准来进行比较来排序,此时就可以基于Comparable接口实现或者基于比较器实现(Comparator接口)

  1. 自然排序:基于Comparable接口
  2. 定制排序:基于Comparator接口

本文均以自定义的Person类为例:

public class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}}

Comparable接口

使用了Comparable接口,意味着此类可排序,使用方法是:在想要实现比较的类中实现Comparable接口并重写compareTo()方法

我们先观察一下Comparable接口的源码:

在这里插入图片描述

我们发现,Comparable接口中只有一个CompareTo方法

观察完毕后,我们看如下实现代码:

//Person.java
//实现Comparable接口
public class Person implements Comparable<Person> {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}//重写compareTo方法,这里按照name(字符串)比较@Overridepublic int compareTo(Person o) {if(this.name.compareTo(o.name) > 0) {return 1;}else if(this.name.compareTo(o.name) < 0) {return -1;}else {return 0;}}
}//Test.java
import java.util.Arrays;public class Test {public static void main(String[] args) {Person[] people = new Person[]{new Person("zhangsan", 23), new Person("lisi", 15),new Person("wangwu", 42)};//实现了Comparable接口后,可以通过Arrays类中的排序方法给对象数组排序了Arrays.sort(people);for(Person p : people) {System.out.println(p);}}
}

打印结果如下:

在这里插入图片描述

  • Comparable接口后面的<>是泛型知识,传入要比较的类即可

  • 实现Comparable接口必须重写CompareTo方法,方法要求返回int类型的值,一般内部实现的逻辑:

    调用方法的对象 > 作为参数的对象,返回正数;调用方法的对象 < 作为参数的对象,返回负数;调用方法的对象 == 作为参数的对象,返回0

  • 一个类实现了Comparable接口,那么就可以调用Arrays类中的sort方法对存放此类对象的数组进行排序

  • 一个实现了Comparable接口的类只能重写一个compareTo方法,这也意味着标准被固定


Comparator接口

前面提到,基于Comparable接口实现比较的标准固定,且不便在原代码修改,这种情况下,我们可以通过Comparator接口(比较器)实现,方法是:定义一个或多个比较器类,实现Comparator接口,并重写Compare方法

我们先观察一下Comparator接口的一部分源码:
在这里插入图片描述

这部分源码显示,Comparator接口中包含compareequals方法,实现了Comparator接口的类可以不重写equals方法,但是一定要重写compare方法

观察完毕后,我们看如下实现代码:

//Person.java
public class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}}//AgeComparator.java
//以年龄比较的比较器
import java.util.Comparator;public class AgeComparator implements Comparator<Person> {@Overridepublic int compare(Person o1, Person o2) {return o1.getAge() - o2.getAge();}
}//NameComparator.java
//以名字比较的比较器
import java.util.Comparator;public class NameComparator implements Comparator<Person> {@Overridepublic int compare(Person o1, Person o2) {return o1.getName().compareTo(o2.getName());}
}//Test.java
import java.util.Arrays;public class Test {public static void main(String[] args) {Person[] people = new Person[]{new Person("zhangsan", 23), new Person("lisi", 15),new Person("wangwu", 42)};//使用时,必须实例化比较器对象AgeComparator ageComparator = new AgeComparator();NameComparator nameComparator = new NameComparator();//正常使用System.out.println(ageComparator.compare(new Person("张三", 16), new Person("李四", 10)));//与Arrays类中的sort方法配合使用Arrays.sort(people, ageComparator);for(Person p : people) {System.out.println(p);}}
}

打印结果如下:

在这里插入图片描述

  • 要比较的对象的类不需要实现Comparator接口,比较器需要实现Comparator接口,并在<>内给出要比较的类,并重写compare方法
  • 重写的compare方法有两个参数,分别是要比较的两个对象,重写的compare方法要求:返回值的正负以及零,表示不同的比较结果。例如,左参数对象大于右参数对象,返回正值;左参数对象小于右参数对象,返回负值;左右参数对象相等,返回0
  • 使用时,必须实例化比较器类对象。可以选择直接调用其中的compare方法比较单一对象,也可以配合Arrays类中的sort方法对对象数组进行排序,此时sort方法需要两个参数:1. 对象数组 2. 比较器对象
  • 比较器可以创建若干个,意味着我们可以定义多个标准,相对灵活一些

区别:

  1. Comparable 相当于 “内部比较器”,Comparator相当于 “外部比较器”
  2. 对于基于Comparable的比较,需要手动实现接口,侵入性比较强,但一旦实现,每次调用该类都有顺序,属于内部顺序
  3. 对于基于Comparator的比较,需要实现一个比较器对象,对待比较类的侵入性弱,但对算法代码实现侵入性强

侵入性:让用户代码产生对框架的依赖,这些代码不能直接脱离框架使用,不利于代码的复用

关于对象的比较,数据结构部分会经常用到


我们的SE部分的补充知识到此结束了,小裤马上会发一篇SE语法合集

http://www.lryc.cn/news/364626.html

相关文章:

  • Nvidia Jetson/Orin +FPGA+AI大算力边缘计算盒子:轨道交通监控系统
  • 笔记 | 软件工程01:从程序到软件
  • 废品回收小程序开发,助力商家拓展回收市场
  • JVM类加载机制和双亲委派
  • 【PyCharm】无法创建虚拟环境,提示:has no attribute CPython3macOsBrew
  • 华为OD刷题C卷 - 每日刷题 12(数组连续和,求最多可以派出多少支团队)
  • 2.1 初识Windows程序
  • EDI系统的使用场景
  • 韩国Neowine推出第三代强加密芯片ALPU-CV
  • golang结构与接口方法实现与交互使用示例
  • C# 判断字符串不等于空的示例
  • 直方图中最大的矩形
  • 分布式锁redisson
  • 将小爱音箱接入 ChatGPT 和豆包ai改造成专属语音助手
  • 短网址生成原理及使用
  • C#调用word组件转pdf,遇到视图保护解决方法
  • NAT端口映射,实现外网访问内网服务器
  • 【面试笔记】嵌入式软件工程师,汽车电子软件相关
  • uniapp小程序开发 | 从零实现一款影视类app (后台接口实现,go-zero微服务的使用)
  • 【C#】委托
  • 【面试题】创建两个线程交替打印100以内数字(一个打印偶数一个打印奇数)
  • PgMP考试结束后多久出成绩?附成绩查询方法
  • springboot项目Redis统计在线用户
  • GNeRF论文理解
  • 0531作业 链表
  • C++ STL - 容器
  • AI生成沉浸式3D世界(空间照片/视频)
  • 【Vue】异步更新 $nextTick
  • 【uCOS-III-编程指南】
  • 2004NOIP普及组真题 2. 花生采摘