首页 > 编程语言 >Java Comparator接口的介绍与使用

Java Comparator接口的介绍与使用

时间:2023-07-14 22:22:52浏览次数:35  
标签:Java Comparator 接口 Person keyExtractor 排序 比较

Java Comparator接口的介绍与使用

什么是Comparator接口?

Comparator接口是一个用于比较两个对象大小的接口,它定义了一个抽象方法compare(T o1, T o2),根据o1和o2的大小返回一个整数值。Comparator接口位于java.util包中,它是一个泛型接口,可以指定比较的对象类型。

Comparator接口的作用是提供一种自定义的比较规则,可以用于对没有实现Comparable接口的类的对象进行排序,或者对实现了Comparable接口的类的对象进行不同的排序。Comparable接口是另一个用于比较对象大小的接口,它定义了一个抽象方法compareTo(T o),根据this和o的大小返回一个整数值。Comparable接口位于java.lang包中,它也是一个泛型接口,可以指定比较的对象类型。

Comparable接口的作用是提供一种自然的比较规则,通常用于实现类似于数字、字符串、日期等有固定大小顺序的类。实现了Comparable接口的类可以直接使用Java中的排序功能对其进行排序,比如使用Collections.sort或Arrays.sort方法。

 

Comparator接口有哪些应用场景?

Comparator接口在Java中有很多应用场景,比如:

  • 当我们需要对一个类的对象进行排序,但是这个类没有实现Comparable接口,或者实现了Comparable接口但是我们想要使用不同的比较规则时,我们可以使用Comparator接口来自定义比较器,并传递给Collections.sort或Arrays.sort方法。
  • 当我们需要对一个Map的键或值进行排序时,我们可以使用Comparator接口来自定义比较器,并传递给TreeMap的构造器或者Collections.sort方法。
  • 当我们需要使用优先队列来存储一些对象时,我们可以使用Comparator接口来自定义比较器,并传递给PriorityQueue的构造器,从而控制对象的优先级。
  • 当我们需要使用Stream API对流中的元素进行排序时,我们可以使用Comparator接口来自定义比较器,并传递给sorted方法,从而实现自定义排序。

这些应用场景都可以体现出Comparator接口的灵活性和实用性,它可以让我们根据不同的需求来定义不同的比较规则,而不需要修改原有的类或者实现多个接口。

如何使用Comparator接口?

要使用Comparator接口,我们需要创建一个实现了该接口的类,并重写compare方法。在compare方法中,我们需要根据我们想要的比较规则来返回相应的整数值。一般来说,如果o1小于o2,则返回负数;如果o1等于o2,则返回零;如果o1大于o2,则返回正数。

例如,我们有一个Person类,包含name, age, id三个属性,我们想要按照年龄从小到大对Person对象进行排序,我们可以创建一个实现了Comparator接口的类,并重写compare方法如下:

class AgeComparator implements Comparator<Person> {
    @Override
    public int compare(Person p1, Person p2) {
        return p1.getAge() - p2.getAge();
    }
}

然后,我们可以使用Collections.sort或Arrays.sort方法对Person对象数组或集合进行排序,并传入一个AgeComparator对象作为第二个参数:

Person[] persons = new Person[5];
persons[0] = new Person("Alice", 20, 1);
persons[1] = new Person("Bob", 25, 2);
persons[2] = new Person("Charlie", 22, 3);
persons[3] = new Person("David", 23, 4);
persons[4] = new Person("Eve", 21, 5);

Arrays.sort(persons, new AgeComparator()); // 使用AgeComparator进行排序

这样,我们就可以按照年龄从小到大对Person对象进行排序了。

Comparator接口如何自定义方法?

除了实现Comparator接口的compare方法外,我们还可以自定义一些其他的方法,用于实现更复杂或更灵活的比较逻辑。自定义方法的一般步骤如下:

  • 定义一个实现了Comparator接口的类,并指定泛型类型。
  • 在类中声明一个或多个自定义方法,根据需要设置参数和返回值类型。
  • 在自定义方法中,根据比较规则,调用compare方法或其他的比较器方法,返回相应的整数值。
  • 在使用Comparator接口的地方,创建一个该类的对象,并调用自定义方法进行比较。

例如,我们想要对Person对象按照年龄从大到小排序,如果年龄相同则按照姓名从小到大排序,如果姓名也相同则按照id从小到大排序,我们可以自定义一个方法如下:

class PersonComparator implements Comparator<Person> {
    @Override
    public int compare(Person p1, Person p2) {
        return p1.getAge() - p2.getAge();
    }

    // 自定义一个按照年龄、姓名、id排序的方法
    public int compareByAgeNameId(Person p1, Person p2) {
        // 先按照年龄降序排序
        int result = compare(p2, p1);
        // 如果年龄相同,则按照姓名升序排序
        if (result == 0) {
            result = p1.getName().compareTo(p2.getName());
        }
        // 如果姓名也相同,则按照id升序排序
        if (result == 0) {
            result = p1.getId() - p2.getId();
        }
        return result;
    }
}

然后,我们可以使用Collections.sort或Arrays.sort方法对Person对象数组或集合进行排序,并传入一个PersonComparator对象,并调用compareByAgeNameId方法作为第二个参数:

Person[] persons = new Person[5];
persons[0] = new Person("Alice", 20, 1);
persons[1] = new Person("Bob", 25, 2);
persons[2] = new Person("Charlie", 22, 3);
persons[3] = new Person("David", 23, 4);
persons[4] = new Person("Eve", 21, 5);

PersonComparator pc = new PersonComparator(); // 创建一个PersonComparator对象
Arrays.sort(persons, pc::compareByAgeNameId); // 使用compareByAgeNameId方法进行排序

这样,我们就可以使用自定义方法实现更复杂或更灵活的比较规则了。

Comparator接口有哪些常用的方法?

除了compare方法外,Comparator接口还提供了一些默认方法和静态方法,用于方便地创建和组合不同的比较器。这些方法主要有:

  • reversed(): 返回一个与当前比较器相反顺序的比较器。
  • thenComparing(Comparator<? super T> other): 返回一个先按照当前比较器进行比较,如果相等则按照other比较器进行比较的复合比较器。
  • thenComparing(Function<? super T, ? extends U> keyExtractor, Comparator<? super U> keyComparator): 返回一个先按照当前比较器进行比较,如果相等则按照keyExtractor提取出来的键值按照keyComparator进行比较的复合比较器。
  • thenComparingInt(ToIntFunction<? super T> keyExtractor): 返回一个先按照当前比较器进行比较,如果相等则按照keyExtractor提取出来的int值进行比较的复合比较器。
  • thenComparingLong(ToLongFunction<? super T> keyExtractor): 返回一个先按照当前比较器进行比较,如果相等则按照keyExtractor提取出来的long值进行比较的复合比较器。
  • thenComparingDouble(ToDoubleFunction<? super T> keyExtractor): 返回一个先按照当前比较器进行比较,如果相等则按照keyExtractor提取出来的double值进行比较的复合比较器。
  • naturalOrder(): 返回一个按照自然顺序进行比较的比较器,要求被比较的对象实现了Comparable接口。
  • reverseOrder(): 返回一个按照自然顺序相反进行比较的比较器,要求被比较的对象实现了Comparable接口。
  • comparing(Function<? super T, ? extends U> keyExtractor, Comparator<? super U> keyComparator): 返回一个按照keyExtractor提取出来的键值按照keyComparator进行比较的比较器。
  • comparing(Function<? super T, ? extends U> keyExtractor): 返回一个按照keyExtractor提取出来的键值按照自然顺序进行比较的比较器,要求键值实现了Comparable接口。
  • comparingInt(ToIntFunction<? super T> keyExtractor): 返回一个按照keyExtractor提取出来的int值进行比较的比较器。
  • comparingLong(ToLongFunction<? super T> keyExtractor): 返回一个按照keyExtractor提取出来的long值进行比较的比较器。
  • comparingDouble(ToDoubleFunction<? super T> keyExtractor): 返回一个按照keyExtractor提取出来的double值进行比较的比较器。
  • nullsFirst(Comparator<? super T> comparator): 返回一个将null值视为最小值,并使用comparator进行非null值比较的比较器。
  • nullsLast(Comparator<? super T> comparator): 返回一个将null值视为最大值,并使用comparator进行非null值比较的比较器。

这些方法可以让我们更灵活地创建和组合不同的比较规则,而不需要每次都定义一个新的类。例如,我们想要对Person对象按照年龄从大到小排序,如果年龄相同则按照姓名从小到大排序,我们可以使用以下代码:

Arrays.sort(persons, Comparator.comparingInt(Person::getAge).reversed().thenComparing(Person::getName));

这样,我们就可以使用一行代码实现复杂的排序规则了。

 

 

 

总结

Comparator接口是一个用于自定义对象大小比较规则的接口,它可以用于对没有实现Comparable接口或需要不同排序规则的类的对象进行排序。Comparator接口有很多常用的方法,可以让我们更方便地创建和组合不同的比较器。Comparator接口是Java中一个非常重要和实用的接口,我们应该掌握它的使用方法和原理。

标签:Java,Comparator,接口,Person,keyExtractor,排序,比较
From: https://www.cnblogs.com/shoshana-kong/p/17555136.html

相关文章

  • Java swing和JavaFX学习笔记
    JAVAFX与JAVASwing的区别与推荐:学习Java界面编程是选择Swing还是JavaFX?_javafxswing_莱迪娜的歌声的博客-CSDN博客swing中一些基础函数介绍:JButton按钮,按钮可以带一些图片或文字JCheckBox复选框JComBox下拉列表框,可以在下拉显示区域显示多个选项JFrame框架类......
  • 大一下java期末设计:学生信息管理系统(荣获班上第一)
    先上java代码:先上java代码:importjava.awt.*;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;importjava.sql.*;importjava.util.Scanner;importjavax.swing.*;publicclasscs2extendsJFrame{publicstaticvoidmain(String[]args......
  • /login接口路径404但是拦截器却显示路径为/error
    参考文献:springboot全局异常处理中的404的/error重复拦截问题(https://blog.csdn.net/qq_35890572/article/details/106529428)问题:loginInterceptor在经过后,目标接口/login报错,又进入拦截器了,但是断点显示路径为/error因为在接口异常后,SpringMVC会去寻找有没有对应异常的统一处理......
  • 学科知识图谱学习平台项目 :技术栈Java、Neo4j、MySQL等超详细教学
    学科知识图谱学习平台项目:技术栈Java、Neo4j、MySQL等超详细教学0.效果展示1.安装教程安装JavaSDK11,下载前需要登录Oracle账号,下载链接,安装教程,测试是否能在命令行工具调用javajava--versionjava17.0.12021-10-19LTSJava(TM)SERuntimeEnvironment(build......
  • java8 LocalData/Time
    ISO_DATE_TIMELStringtimeString=LocalDateTime.now().atOffset(ZoneOffset.ofHours(8)).format(DateTimeFormatter.ISO_DATE_TIME);System.out.println(timeString);//2023-07-14T18:28:23.056+08:00增加与减小LocalDatedate=LocalDate.now().minusMonths(1);LocalDa......
  • Java POM Dependency
     <projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd">......
  • java拦截器获取POST请求体后Controller异常Required request body is missing OR Stre
    解决办法参考文档:https://blog.csdn.net/qierkang/article/details/88544691springboot拦截器获取POST请求体后导致Controller中@RequestBody参数异常RequiredrequestbodyismissingORStreamclosed.1.为什么会报这个错?因为http的body只能读取一次。2.为什么body设计为只......
  • Java入门13(socket)
    Socket编程(网络通信)服务器端Demo(ServreSocket)​ 创建服务端时,如果不提供IP地址,则默认为本地连接(127.0.0.1),但是一定需要手动配置监听端口!publicstaticvoidmain(String[]args){//如果不提供IP地址,默认localhost//但是服务器端的端口号需要手动指令try(Serv......
  • java--String类的常用方法
    一、获取1、length()  获取字符串长度Stringstr="ahcckmvevawe";System.out.println(str.length());//输出122、charAt(intindex)  返回下标对应的字符Stringstr="ahcckmvevawe";System.out.println(str.charAt(4));//输出k3、indexOf()  返回字符对......
  • JavaWeb基础:安装tomcat和maven
    JavaWeb基础:安装tomcat和maventomcat闪退问题下载zip即可,无需配置,只需运行相关文件即可文档所在位置:D:\Environment\apache-tomcat-9.0.78\bin开启:startup.bat关闭:shutdown.batjava8不适用tamcat10及以上版本解决办法:https://blog.csdn.net/egegerhn/article/details/1260......