自定义排序方式
在java中,要实现自定义排序可以使用两种方法:
- 让排序的对象的类实现Comparable接口
- 新建一个类实现比较器Comparator接口
Comparable接口
Comparable接口中有一个compareTo(T o)
方法:
public int compareTo(T o);
compareTo()
方法用于将 Number 对象与方法的参数进行比较。可用于比较 Byte, Long, Integer等。
该方法用于两个相同数据类型的比较,两个不同类型的数据不能用此方法来比较。
实例:
public class Test{
public static void main(String args[]){
Integer x = 5;
System.out.println(x.compareTo(3));
System.out.println(x.compareTo(5));
System.out.println(x.compareTo(8));
}
}
输出:
1
0
-1
返回值:
- 如果指定的数与参数相等返回 0。
- 如果指定的数小于参数返回 -1。
- 如果指定的数大于参数返回 1。
实现Comparable接口自定义排序规则
这种方法需要要进行排序的对象的那个类实现Comparable接口,泛用性比较高,在类中重写一次Comparable接口中的compareTo()
方法,再对该对象进行排序时,排序的方式都是使用的自己定义的规则。
但是这种方法不能对没有实现Comparable接口的类对象使用,比如我们就不能使用这种方式对String类型的排序方式进行改变,因为我们不能去修改String类。
实例:
自定义一个学生类型,实现Comparable接口,按照学生的年龄逆序排序:
public static void main(String[] args) {
Student[] students=new Student[4];
for(int i=0;i<4;i++){
students[i]=new Student();
}
students[0].age=10;
students[0].name="li";
students[0].num=1;
students[1].age=22;
students[1].name="li11";
students[1].num=2;
students[2].age=4;
students[2].name="li222";
students[2].num=3;
students[3].age=40;
students[3].name="l";
students[3].num=4;
Arrays.sort(students);
System.out.println(Arrays.toString(students));
}
class Student implements Comparable<Student>{
String name;
int age;
int num;
public int getNum() {
return num;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student o) {
return o.age-age;
}
}
输出:
[Student{name='l', age=40}, Student{name='li11', age=22}, Student{name='li', age=10}, Student{name='li222', age=4}]
默认的sort是升序排序,重写了Comparable中的方法compareTo,让sort按照student的年龄倒序排序。
comparator接口(比较器)
comparator接口(比较器)中有一个compare方法:
compare(Object o1,Object o2)
:比较o1和o2的大小
返回值:
- 如果方法返回正整数,则表示o1大于o2,
- 如果返回0,表示二者相等,
- 如果返回负整数,表示o1小于o2.
新建类实现Comparator接口实现排序规则
新建一个类实现比较器Comparator接口,这种方法需要在sort方法中new 这个类
这种方法的弊端就是每次排序都需要重写一次排序规则,也就是重写Comparator接口中的compare()
方法。
为了简便,这种方法通常用内部类或lambda表达式实现。
普通实现:
student类的数据仍旧和上文中一样,此次按照名字的长度顺序排序:
class StudentCompare implements Comparator<Student> {
@Override
public int compare(Student o1,Student o2) {
return o1.name.length()-o2.name.length();
}
}
Arrays.sort(students,new StudentCompare());
System.out.println(Arrays.toString(students));
输出:
[Student{name='l', age=40}, Student{name='li', age=10}, Student{name='li11', age=22}, Student{name='li222', age=4}]
内部类实现:
Arrays.sort(students,new StudentCompare(){
@Override
public int compare(Student o1,Student o2) {
return o1.name.length()-o2.name.length();
}
});
lambda表达式实现:
Arrays.sort(students,(o1,o2)->{
return o1.name.length() - o2.name.length();
});
或者更加简洁的形式:
Arrays.sort(students, Comparator.comparingInt(o -> o.name.length()));
注意:
- Array.sort()不能对int数组进行自定义排序,只能对Integer数组使用,因为int数组没有实现该接口。Array.sort()不能对基本类型使用自定义排序,想要使用Arrays.sort()排序可以将基本类型转换为对应的包装器类型,Arrays.sort()只能用于对象类型的数据自定义排序规则。(当然,可以使用sort()方法对基本类型升序排序,只是不能自定义排序)
- compareTo()方法比较的时候是按照ASCII码逐位比较的.
lambda表达式介绍:
参数为接口时,可以使用lambda表达式。
- Lambda表达式的标准格式为:(参数类型 参数名称) ‐> { 代码语句 }
- 小括号内的语法与传统方法参数列表一致:无参数则留空;多个参数则用逗号分隔。
- ‐>是新引入的语法格式,代表指向动作。
- 大括号内的语法与传统方法体要求基本一致。
- Lambda省略格式
- 小括号内参数的类型可以省略;
- 如果小括号内有且仅有一个参,则小括号可以省略;
- 如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号。
- Lambda的使用前提
- 使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法。无论是JDK内置的 Runnable 、 Comparator 接口还是自定义的接口,只有当接口中的抽象方法存在且唯一 时,才可以使用Lambda。
- 使用Lambda必须具有上下文推断。也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例。