【Java 学习】Comparable接口 和 Comparator接口,掌控排序逻辑解析,深入 Comparable 和 Comparator 的优雅切换

06-02 658阅读

💬 欢迎讨论:如对文章内容有疑问或见解,欢迎在评论区留言,我需要您的帮助!

👍 点赞、收藏与分享:如果这篇文章对您有所帮助,请不吝点赞、收藏或分享,谢谢您的支持!

🚀 传播技术之美:期待您将这篇文章推荐给更多对需要学习Java语言、低代码开发感兴趣的朋友,让我们共同学习、成长!

1. Comparable接口

1.1 为什么要使用Comparable接口

先看代码两组代码:

代码1:

import java.util.Arrays;
public class Main {
    public static void main(String[] args) {
        // 创建一个数组
        String[] strs = {"李华","小明", "小红"};
        // 对数组进行排序
        Arrays.sort(strs);
        // 打印
        System.out.println(Arrays.toString(strs));
    }
}

上述代码可以打印出比较的后的顺序。

代码2:

import java.util.Arrays;
class Student{
    public String name;
    public int age;
    public Student(String name, int age){
        this.name = name;
        this.age = age;
    }
}
public class Main {
    public static void main(String[] args) {
        Student[] stus = {new Student("小明",19), new Student("小红",20), new Student("小刚",18)};
        // 对数组进行排序
        Arrays.sort(stus);
        // 打印
        System.out.println(Arrays.toString(stus));
    }
}

上述的代码发生报错:

【Java 学习】Comparable接口 和 Comparator接口,掌控排序逻辑解析,深入 Comparable 和 Comparator 的优雅切换

点击之后会跳转到如下图的代码:

【Java 学习】Comparable接口 和 Comparator接口,掌控排序逻辑解析,深入 Comparable 和 Comparator 的优雅切换

代码如下:

private static int countRunAndMakeAscending(Object[] a, int lo, int hi) {
        assert lo = 0)
                runHi++;
        }
        return runHi - lo;
    }

在源代码中,使用Array.sort()会把引用类型强制转化成Comparable

(Comparable) a[runHi++] 强制把 a引用变量转化成Comparable 类型,但是我们写的Student并没有实现接口Comparable ,所以发生报错

那么,String是不是实现了 Comparable接口呢?

看一看String的源代码:

【Java 学习】Comparable接口 和 Comparator接口,掌控排序逻辑解析,深入 Comparable 和 Comparator 的优雅切换

那为什么都必须实现这个接口呢?

在讲解接口的时已经说过,接口是一个标准,大家都执行这个标准,设计出的程序才能通用。

如:

String 实现了Comparable接口,它可以用Arrays.sort()进行快速排序。

1.2 Comparable 接口的语法

特点:

(1)用于定义默认的排序规则。

(2)实现了 Comparable 的类对象可以直接通过 Collections.sort() 或 Arrays.sort() 方法进行排序。

(3)它属于对象本身的一部分,默认定义了对象之间的比较逻辑。

Comparable 接口中只有一个方法:

int compareTo(T o);

方法参数与返回值:

(1)参数:T o,表示要比较的对象。

(2)返回值:

-----------返回负数:当前对象小于传入对象。

-----------返回零:当前对象等于传入对象。

-----------返回正数:当前对象大于传入对象。

语法:

public class 类名 implements Comparable{
    
    @Override
    public int compareTo(参数){
        //...
        
        return 返回值;
    }
}

示例:

//                               Comparable 什么类就需要填什么
public class Student implements Comparable {
    private String name;
    private int score;
    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }
    // Comparable 接口只有此一个方法,实现 compareTo 方法
    @Override
    public int compareTo(Student other) {
        return this.score - other.score; // 按照分数升序排序
        // return other.score - this.score 按照分数降序排序
    }
}

1.3 Comparable 的使用

使用compareTo函数:

import java.util.Arrays;
class Student implements Comparable{
    public String name;
    public int age;
    public Student(String name, int age){
        this.name = name;
        this.age = age;
    }
    @Override
    public int compareTo(Student s){
        return this.age - s.age;
    }
}
public class Main {
    public static void main(String[] args) {
        Student s1 = new Student("小明",19);
        Student s2 = new Student("小红",20);
        
        System.out.println(s1.compareTo(s2));
    }
}

返回的是19 - 20 的值:

【Java 学习】Comparable接口 和 Comparator接口,掌控排序逻辑解析,深入 Comparable 和 Comparator 的优雅切换

使用Ayyars.sort()按照年龄升序排序:

import java.util.Arrays;
class Student implements Comparable{
    public String name;
    public int age;
    public Student(String name, int age){
        this.name = name;
        this.age = age;
    }
    @Override
    public int compareTo(Student s){
        return this.age - s.age; // 升序排序
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Main {
    public static void main(String[] args) {
        Student[] stus = {new Student("小明",19), new Student("小红",20), new Student("小刚",18)};
        // 排序前
        System.out.println("排序前:"+ Arrays.toString(stus));
        // 对数组进行排序
        Arrays.sort(stus);
        // 排序后
        System.out.println("排序后"+Arrays.toString(stus));
    }
}

【Java 学习】Comparable接口 和 Comparator接口,掌控排序逻辑解析,深入 Comparable 和 Comparator 的优雅切换

Arrays.sort()排序使用Student中的compareTo函数了吗?我们怎么知道呢?

在compareTo中添加一个加打印语句:

@Override
    public int compareTo(Student s){
        System.out.println("comppareTo()");
        return this.age - s.age;
    }

再次运行,结果:

【Java 学习】Comparable接口 和 Comparator接口,掌控排序逻辑解析,深入 Comparable 和 Comparator 的优雅切换

很明显,使用Arrays.sort()时调用了compareTo函数。

2. Comparator 接口

2.1 为什么要有 Comparator 接口

一个有年龄排序方法的类:

class Student implements Comparable{
    public String name;
    public int age;
    public int score;
    public Student(String name, int age, int score){
        this.name = name;
        this.age = age;
        this.score = score;
    }
    @Override
    public int compareTo(Student s){
        return this.age - s.age; // 升序排序
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

Comarable 接口只能被重写一次,只能进行年龄比较,但是,我们要想进行排序的是分数score, 怎么办呢?

此时,Comarator接口可以解决这个问题。Comparator有很强的灵活性,可以设计比较任意的属性。

2.2 Comparator 接口的语法

特点:

(1)用于定义自定义的排序规则。

(2)它是一个独立的比较器,与对象本身的定义无关。

(3)当需要对同一类的对象应用多种排序规则时,Comparator 更加灵活。

(4)Comparator 的对象可以传递给 Collections.sort() 或 Arrays.sort() 方法。

Comparator 接口中有两个常用方法:

int compare(T o1, T o2);
boolean equals(Object obj) //判断是否与另一个比较器相等(通常很少需要重写)

语法:

public class 类名 implements Comparator{
    
    @Override
    public int compare(参数){
        //...
        
        return 返回值;
    }
}

2.3 Comparator 接口的使用

  1. 比较两个对象的成绩:

Studnet类:

public class Student {
    public String name;
    public int age;
    public int score;
    public Student(String name, int age, int score){
        this.name = name;
        this.age = age;
        this.score = score;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

比较类:

import java.util.Comparator;
                        // 注意,这里的类需要填进行比较的类
class ScoreSort implements Comparator{
	// 重写比较函数
	// 注意,这里的参数有两个
    @Override
    public int compare(Student s1, Student s2){
        return s1.score - s2.score;
    }
}

两个对象的score进行比较:

public class Main {
    public static void main(String[] args) {
        // 创建两个对象
        Student s1 = new Student("小明",19,80);
        Student s2 = new Student("小红",20,70);
        // 创建一个排序对象
        ScoreSort ss = new ScoreSort();
		
		// 打印出比较的结果
        System.out.println(ss.compare(s1,s2));
    }
}

结果:

【Java 学习】Comparable接口 和 Comparator接口,掌控排序逻辑解析,深入 Comparable 和 Comparator 的优雅切换

  1. 比较一个数组的成绩:

Arrays.sort()可以填入两个参数,只需要把Arrays.sort(array,object)中的object换成排序对象即可。

public class Main {
    public static void main(String[] args) {
        Student[] stus = {new Student("小明",19,80),
                new Student("小红",20,70), new Student("小刚",18,90)};
        // 排序前
        System.out.println("排序前:"+ Arrays.toString(stus));
        // 创建排序的对象
        ScoreSort scoreSort = new ScoreSort();
        // 对数组进行排序
        Arrays.sort(stus,scoreSort);  //需要添加排序对象
        // 排序后
        System.out.println("排序后"+Arrays.toString(stus));
    }
}

结果:

【Java 学习】Comparable接口 和 Comparator接口,掌控排序逻辑解析,深入 Comparable 和 Comparator 的优雅切换

3 Comparable 和 Comparator 的比较

Comparable 和 Comparator 的核心区别

特性ComparableComparator
用途定义对象的默认排序规则定义自定义的排序规则
位置排序逻辑在对象内部实现排序逻辑在外部定义
接口方法compareTo(T o)compare(T o1, T o2)
实现方式对象类实现 Comparable 接口通过实现 Comparator 接口创建比较器
灵活性只能定义一种排序规则可以定义多种排序规则
使用场景对象有一个自然排序对象需要多种排序规则或自定义排序
修改类代码的需求必须修改类的代码以实现接口不需要修改类的代码,可在外部定义排序逻辑

选择 Comparable 还是 Comparator?

使用场景选择
类的排序逻辑是固定的,且只有一种排序方式。Comparable
类的排序逻辑可能有多种(如按年龄、按名字)。Comparator
类的代码无法修改(如第三方库类)。Comparator
需要更灵活的排序方式。Comparator
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码