【JAVA学习之路 | 提高篇】Java比较器(comparable) &&(comparator)

简介: 【JAVA学习之路 | 提高篇】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;
    }
 
    @Override
    public 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();
    }
 
    @Override
    public 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)方法.

@Override
    public 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>() {
            @Override
            public 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方法中.

相关文章
|
7天前
|
Java 调度 开发者
Java线程池ExecutorService学习和使用
通过学习和使用Java中的 `ExecutorService`,可以显著提升并发编程的效率和代码的可维护性。合理配置线程池参数,结合实际应用场景,可以实现高效、可靠的并发处理。希望本文提供的示例和思路能够帮助开发者深入理解并应用 `ExecutorService`,实现更高效的并发程序。
30 10
|
21天前
|
Java 程序员
Java 排序神器:Comparable 和 Comparator 该怎么选?
嗨,大家好,我是小米!今天和大家聊一聊Java社招面试中常考的经典问题——Comparable和Comparator的区别。Comparable定义对象的自然排序,适用于单一固定的排序规则;Comparator则是策略接口,用于定义自定义排序规则,适用于多样化或多变的排序需求。掌握这两者的区别是理解Java排序机制的基础,也是面试中的加分题。结合实际项目场景深入探讨它们的应用,能更好地打动面试官。如果你觉得有帮助,欢迎点赞、收藏、分享,期待你的一键三连!我们下期见~ 我是小米,一个喜欢分享技术的程序员,关注我的微信公众号“软件求生”,获取更多技术干货!
44 20
|
10天前
|
Java 数据库连接 数据库
【潜意识Java】深度分析黑马项目《苍穹外卖》在Java学习中的重要性
《苍穹外卖》项目对Java学习至关重要。它涵盖了用户管理、商品查询、订单处理等模块,涉及Spring Boot、MyBatis、Redis等技术栈。
42 4
|
10天前
|
前端开发 Java 数据库连接
【潜意识Java】深度解读JavaWeb开发在Java学习中的重要性
深度解读JavaWeb开发在Java学习中的重要性
24 4
|
10天前
|
存储 移动开发 算法
【潜意识Java】Java基础教程:从零开始的学习之旅
本文介绍了 Java 编程语言的基础知识,涵盖从简介、程序结构到面向对象编程的核心概念。首先,Java 是一种高级、跨平台的面向对象语言,支持“一次编写,到处运行”。接着,文章详细讲解了 Java 程序的基本结构,包括包声明、导入语句、类声明和 main 方法。随后,深入探讨了基础语法,如数据类型、变量、控制结构、方法和数组。此外,还介绍了面向对象编程的关键概念,例如类与对象、继承和多态。最后,针对常见的编程错误提供了调试技巧,并总结了学习 Java 的重要性和方法。适合初学者逐步掌握 Java 编程。
30 1
|
2月前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
2月前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。
|
Java
【Java】Comparable和Comparator接口
【Java】Comparable和Comparator接口
502 0
【Java】Comparable和Comparator接口
|
Java 编译器
深度解析Java中的Comparable接口和Comparator接口
深度解析Java中的Comparable接口和Comparator接口
152 0
|
Java
【错误记录】Java 中 ArrayList 排序 ( 使用 Comparator 接口时注意 compare 返回值是 -1 和 +1 )
【错误记录】Java 中 ArrayList 排序 ( 使用 Comparator 接口时注意 compare 返回值是 -1 和 +1 )
197 0
【错误记录】Java 中 ArrayList 排序 ( 使用 Comparator 接口时注意 compare 返回值是 -1 和 +1 )