【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方法中.

相关文章
|
2月前
|
XML Java 编译器
Java学习十六—掌握注解:让编程更简单
Java 注解(Annotation)是一种特殊的语法结构,可以在代码中嵌入元数据。它们不直接影响代码的运行,但可以通过工具和框架提供额外的信息,帮助在编译、部署或运行时进行处理。
98 43
Java学习十六—掌握注解:让编程更简单
|
1月前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
2月前
|
存储 SQL 小程序
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
这篇文章详细介绍了Java虚拟机(JVM)的运行时数据区域和JVM指令集,包括程序计数器、虚拟机栈、本地方法栈、直接内存、方法区和堆,以及栈帧的组成部分和执行流程。
40 2
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
|
1月前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。
|
2月前
|
小程序 Oracle Java
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
这篇文章是关于JVM基础知识的介绍,包括JVM的跨平台和跨语言特性、Class文件格式的详细解析,以及如何使用javap和jclasslib工具来分析Class文件。
59 0
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
|
2月前
|
存储 算法 Java
带你学习java的数组军队列
带你学习java的数组军队列
39 0
|
2月前
|
Java 大数据 开发工具
java学习——环境准备(1)
java学习——环境准备(1)
43 0
|
Java 编译器
深度解析Java中的Comparable接口和Comparator接口
深度解析Java中的Comparable接口和Comparator接口
144 0
|
Java
【Java】Comparable和Comparator接口
【Java】Comparable和Comparator接口
487 0
【Java】Comparable和Comparator接口
|
Java
【错误记录】Java 中 ArrayList 排序 ( 使用 Comparator 接口时注意 compare 返回值是 -1 和 +1 )
【错误记录】Java 中 ArrayList 排序 ( 使用 Comparator 接口时注意 compare 返回值是 -1 和 +1 )
187 0
【错误记录】Java 中 ArrayList 排序 ( 使用 Comparator 接口时注意 compare 返回值是 -1 和 +1 )
下一篇
DataWorks