【java】深入理解自然排序

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

对于int数组,字符串数组来说,他们是很容易比较大小的。你可以自己写一个快排算法,或者直接调用java中的排序接口Arrays.sort()来实现对数组的排序。但如果我们想对对象数组进行排序,该怎么做呢,java身为一个面向对象的语言,自然不会留下这样的缺漏,我们甚至仍旧可以对对象数组调用Arrays.sort()方法,实现排序功能,这就是所谓的java自然排序。

/*
普通数组的排序
*/
public static void main(String[] args) {
    String[] strs = {"abc","ab","aa","ac"};
    System.out.println("strs = " + Arrays.toString(strs));
    Arrays.sort(strs);
    System.out.println("strs = " + Arrays.toString(strs));

    int[] ints = {1,4,6,2,7};
    System.out.println("ints = " + Arrays.toString(ints));
    Arrays.sort(ints);
    System.out.println("ints = " + Arrays.toString(ints));
}
复制代码

显然,当对对象数组进行排序的时候,你应当指出给对象排大小的依据,比如学生对象的id,成绩等都可以作为排序依据。为了能让JVM找到这个依据,我们需要给学生类实现一个能排序的功能接口,这样我们才能分辨那种类的对象能进行排序,哪种类不能。

这个功能接口,就是Comparable接口,这是java已经给出的一个接口,我们可以看一下源码(以java8为例):

image.png

在这个接口中只有一个待实现的方法,叫compareTo方法。

image.png

这个方法就是我们用Arrays.sort()进行排序时的依据。compareTo方法的待实现功能为:

将当前对象(this)与指定的对象(就是这里传入的参数o)进行比较。返回值负整数、零或正整数,因为此对象较小大于、等于或大于指定对象。

既然compareTo的逻辑已经给定,那我们只需指定用对象的哪个属性来进行排序就ok。

比如我们来给学生类用分数指定排序依据。

class Student implements Comparable<Student>{
    String name;
    private int score;

    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }

    public int getScore() {
        return score;
    }

    @Override
    public String toString() {
        //toString方法体
    }

    @Override
    public int compareTo(Student o) {
        //认为分数高的学生排在后面,分数低的排前面
        return getScore()-o.getScore();
    }
}
复制代码

接下来就是见证奇迹的时刻!一旦我们实现了Comparable借口,在对象的类中重写了compareTo方法,就可以调用Arrays.sort()对对象进行排序了!

import java.util.Arrays;

public class Ex2 {
    public static void main(String[] args) {
        //创建学生对象数组
        Student[] students = new Student[4];
        students[0] = new Student("商见曜",100);
        students[1] = new Student("龙悦红",70);
        students[2] = new Student("蒋白棉",99);
        students[3] = new Student("白晨",88);
        Arrays.sort(students);
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

复制代码

image.png 到这里自然排序的基本使用就差不多了,不过我们可以更优雅一点,如果我们想排序对象的类没有实现过compareable接口,那么非得再重新去修改类的源码才能添加一个排序功能吗?这也太不优雅了!

事实上在idea里输入Arrays.sort,有多个方法可供选择,这些方法构成方法重载,其中一个方法有两个参数:

image.png

第二个参数是一个新功能接口的实现子类,这个功能接口叫做Comparoter,他的功能和Comparable类似,也是在sort对对象排序时提供排序依据的。他的使用方法是单独实现他的子类对象,然后在sort方法里作为参数被调用。这时,我们就不需要在对象的类里实现comparable接口了(注意!comparable接口和comparator接口是两个接口!)

Arrays.sort(students,(o1,o2)->o1.getScore()-o2.getScore());
复制代码

第二个参数就是comparator接口的子类对象,用的是lambda表达式的格式,这里实现的抽象方法是comparator里的compare方法。规则和comparable里的compareTo方法一样,不再赘述。

image.png

猜你喜欢

转载自juejin.im/post/7101598232563679263