持续创作,加速成长!这是我参与「掘金日新计划 · 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为例):
在这个接口中只有一个待实现的方法,叫compareTo方法。
这个方法就是我们用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);
}
}
}
复制代码
到这里自然排序的基本使用就差不多了,不过我们可以更优雅一点,如果我们想排序对象的类没有实现过compareable接口,那么非得再重新去修改类的源码才能添加一个排序功能吗?这也太不优雅了!
事实上在idea里输入Arrays.sort,有多个方法可供选择,这些方法构成方法重载,其中一个方法有两个参数:
第二个参数是一个新功能接口的实现子类,这个功能接口叫做Comparoter,他的功能和Comparable类似,也是在sort对对象排序时提供排序依据的。他的使用方法是单独实现他的子类对象,然后在sort方法里作为参数被调用。这时,我们就不需要在对象的类里实现comparable接口了(注意!comparable接口和comparator接口是两个接口!)
Arrays.sort(students,(o1,o2)->o1.getScore()-o2.getScore());
复制代码
第二个参数就是comparator接口的子类对象,用的是lambda表达式的格式,这里实现的抽象方法是comparator里的compare方法。规则和comparable里的compareTo方法一样,不再赘述。