比较器
比较器是自己定义的一种大小的判断标准,在对自定义的类型排序往往要用到比较器,类似于C++中对大于,小于,等于的运算符重载。
1.外部比较器
java.util.Comparator;该接口内部提供有一个int compare(T o1, T o2);方法,我们可以通过实现该接口,然后覆写该接口的compare方法来实现外部比较器。
其中该方法的返回值总公有三种情况:
- 大于0,表示 o1 > o2
- 等于0,表示 o1==o2
- 小于0,表示 o1 < o2
使用方式如下:
自定义一个Student类,用来排序
public class Student {
private String name;
private int age;
private int id;
public Student(String name, int age, int id) {
this.name = name;
this.age = age;
this.id = id;
}
public int getAge() {
return age;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "name:" + this.name + "|" + "age:" + this.age + "|" + "id:" + this.id;
}
}
定义按照年龄比较的比较器
import java.util.Comparator;
public class CompareAge implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge() - o2.getAge();
}
}
测试代码:
public class Test {
public static void main(String[] args) {
Student[] arr = new Student[4];
arr[0] = new Student("Tom",23,2);
arr[1] = new Student("Jack",26,7);
arr[2] = new Student("Lucy",20,9);
arr[3] = new Student("Danny",18,6);
System.out.println("************排序前*************");
for(Student stu : arr){
System.out.println(stu);
}
Arrays.sort(arr,new CompareAge()); //将比较器对象作为参数传进去
System.out.println("************排序后*************");
for(Student stu : arr){
System.out.println(stu);
}
}
}
运行结果:
其中该接口是一个函数式编程接口,但是该接口中却有两个抽象方法,经过搜素,原来第二个抽象方法equals本身已经被Object类实现了而所有来都继承了Object类,因此也就没有实现的必要了。因此不用这么麻烦只需一个lambda表达式即可。>
使用Lambda表达式简化代码
Arrays.sort(arr,( s1, s2) -> {return s1.getAge() - s2.getAge();});
2.内部比较器
public interface Comparable,该接口内部有一个public int compareTo(T o);方法覆写该方法来定义排序规则。但为什么该方法只有一个参数?最起码有两个对象才能进行比较。这是因为该方法是一个普通方,因此当我们调用该方法的时候就会产生一个当前对象this。该方法的返回值也是三种情况:
- 大于0,表示 当前对象 > 方法参数
- 等于0,表示当前对象 == 方法参数
- 小于0,表示 当前对象 < 方法参数
代码演示:
public class Student implements Comparable<Student> {
private String name;
private int age;
private int id;
public Student(String name, int age, int id) {
this.name = name;
this.age = age;
this.id = id;
}
public int getAge() {
return age;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "name:" + this.name + "|" + "age:" + this.age + "|" + "id:" + this.id;
}
// 先按照年龄排序,若年龄相同则按照Id排序
@Override
public int compareTo(Student o) {
if(this.getAge() > o.getAge()){
return 1;
}else if(this.getAge() == o.getAge()){
if(this.getId() > o.getId()){
return 1;
}else if(this.getId() == o.getId()){
return 0;
}else{
return -1;
}
}else{
return -1;
}
}
}
有了该方法就不必在传比较器了。
测试代码:
public class Test {
public static void main(String[] args) {
Student[] arr = new Student[4];
arr[0] = new Student("Tom",23,2);
arr[1] = new Student("Jack",26,7);
arr[2] = new Student("Lucy",23,9);
arr[3] = new Student("Danny",18,6);
System.out.println("************排序前*************");
for(Student stu : arr){
System.out.println(stu);
}
Arrays.sort(arr);
System.out.println("************排序后*************");
for(Student stu : arr){
System.out.println(stu);
}
}
}
运行结果:
那么如果两种方式都写会按照哪种方式进行排序呢?
public static void main(String[] args) {
Student[] arr = new Student[4];
arr[0] = new Student("Tom",23,2);
arr[1] = new Student("Jack",26,7);
arr[2] = new Student("Lucy",23,9);
arr[3] = new Student("Danny",18,6);
System.out.println("************排序前*************");
for(Student stu : arr){
System.out.println(stu);
}
// 比较器中使用id进行排序,类中的compareTo使用age排序
Arrays.sort(arr,(s1,s2) -> {return s1.getId() - s2.getId();});
System.out.println("************排序后*************");
for(Student stu : arr){
System.out.println(stu);
}
}
运行结果:
很明显是按照外部比较器的方式进行排序的,因此当别人提供给我们一个类,我们不满足该类内部的比较方式,且又不能动别人代码的时候,我们就可以自定义外部比较器,来实现满足我们需求的排序方式。