Comparable<T>和Comparator<T>是Java中适用于不同情景下的用来对数据进行比较(排序)的两个接口。
下面举例展示Comparable接口的使用:
情景:有一个存放6个student的数组,每个student有age、name、number三个属性,要求按照number升序,age降序,name按字符串长度升序 的规则对数组中的student进行排序。
代码演示:
定义一个Student类,实现Comparable<T>接口,重写comparaTo方法,在方法中制定规则
class Student implements Comparable<Student> {
private int age;
private int number;
private String name;
public Student(int age, int number, String name) {
this.age = age;
this.number = number;
this.name = name;
}
public Student() {
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", number=" + number +
", name='" + name + '\'' +
'}';
}
@Override
/**
* number升序
* age降序
* name按长度升序
*/
public int compareTo(Student o) {
int i = this.number - o.number;
int j = this.age - o.age;
int k = this.name.length()-o.name.length();
return i != 0 ? i : (j != 0 ? -j : k);
}
}
关于compareTo方法的使用规则:
this可以看成前面已经经过比较的数据,o可以看成后面新来的将要进行比较的数据。返回正数则表示o因该排在this前面,返回负数则表示o应该排在this后面,返回0则表示两个没有前后之分。若方法体中只写return一个正数,则这组数据排列顺序不变,如果只写return一个负数,则将原来的排列顺序进行反转。(例子中采用三目运算符进行逻辑判断,也可以采用if()语句)
下面定义测试类检验排序结果:
public class ComparableDemo {
public static void main(String[] args) {
//创建学生并放入数组
Student[] stuArr = {
new Student(18, 101, "张三"),
new Student(18, 101, "张三子"),
new Student(19, 101, "李四"),
new Student(19, 102, "张四"),
new Student(18, 103, "张十三"),
new Student(17, 103, "王五")
};
//调用java.util.Arrays.sort方法
java.util.Arrays.sort(stuArr);
for (Student student : stuArr) {
System.out.println(student);
}
}
}
运行结果:
下面举例展示Comparator接口的使用:
情景:有一个存放6个student的数组,每个student有age、name、number三个属性。
需求一:按照number、age、name依次升序排序
需求二:按照number、age、name依次降序排序
需求三:按照number升序,age降序,name按字典顺序排序
······
要求所有需求都在同一个测试类中实现。
代码演示:
·定义学生类:(该类只是一个普通的学生类,没有实现任何接口)
-
class Student2 { private int age; private int number; private String name; public Student2(int age, int number, String name) { this.age = age; this.number = number; this.name = name; } public int getAge() { return age; } public int getNumber() { return number; } public String getName() { return name; } public Student2() { } @Override public String toString() { return "Student2{" + "age=" + age + ", number=" + number + ", name='" + name + '\'' + '}'; } }
·接下来定义比较器类,实现Comparator接口,重写compare方法。 ComparatorMachine01用来实现需求一;ComparatorMachine03用来实现需求三;需求二我们将比较器类写成内部类形式或Lambda表达式来实现。比较器类须实现Comparator<T>接口,T为比较对象的数据类型。
/**
* 比较器01
* 所有内容升序排序
*/
class ComparatorMachine01 implements Comparator<Student2> {
@Override
public int compare(Student2 o1, Student2 o2) {
int i = o1.getNumber() - o2.getNumber();
int j = o1.getAge() - o2.getAge();
int k = o1.getName().compareTo(o2.getName());
return i != 0 ? i : (j != 0 ? j : k);
}
}
/**
* 比较器03
*/
class ComparatorMachine03 implements Comparator<Student2> {
@Override
public int compare(Student2 o1, Student2 o2) {
int i = o1.getNumber() - o2.getNumber();
int j = o1.getAge() - o2.getAge();
int k = o1.getName().compareTo(o2.getName());
//返回正数则排序时o2放前面;返回负数则o2放后面
return i != 0 ? i : (j != 0 ? -j : k);
}
}
关于compare方法的使用规则:
o1和o2为两个将要进行比较的数据。返回正数则表示o2因该排在o1前面,返回负数则表示o2应该排在o1后面,返回0则表示两个没有前后之分。若方法体中只写return一个正数,则这组数据排列顺序不变,如果只写return一个负数,则将原来的排列顺序进行反转。
(name采用String类的compareTo方法,即按照字符在字典中的顺序排序。)
·接下来写一个测试类实现上述需求:
public class ComparatorDemo {
public static void main(String[] args) {
Student2[] stuArr2 = {
new Student2(18, 101, "张三"),
new Student2(18, 101, "张三子"),
new Student2(19, 101, "李四"),
new Student2(19, 102, "张四"),
new Student2(18, 103, "张十三"),
new Student2(17, 103, "王五")
};
//调用java.util.Arrays.sort方法,传入待排序的数组和符合需求的比较器对象
Arrays.sort(stuArr2, new ComparatorMachine01());//调用比较器01 实现升序排序
for (Student2 student : stuArr2) {
System.out.println(student);
}
System.out.println();
//采用Lambda表达式
Arrays.sort(stuArr2, (o1, o2) -> {
int i = o1.getNumber() - o2.getNumber();
int j = o1.getAge() - o2.getAge();
int k = o1.getName().compareTo(o2.getName());
return i != 0 ? -i : (j != 0 ? -j : -k);
});
/* 等价于下面代码(以内部类形式)
Arrays.sort(stuArr2, new Comparator<Student2>() {
@Override
public int compare(Student2 o1, Student2 o2) {
int i = o1.getNumber() - o2.getNumber();
int j = o1.getAge() - o2.getAge();
int k = o1.getName().compareTo(o2.getName());
return i != 0 ? -i : (j != 0 ? -j : -k);
}
});*/
for (Student2 student : stuArr2) {
System.out.println(student);
}
System.out.println();
//调用比较器03 实现number升序,age降序,name升序
Arrays.sort(stuArr2, new ComparatorMachine03());
for (Student2 student : stuArr2) {
System.out.println(student);
}
}
}
运行结果:
我们可以发现,如果需要对一组数据进行多种规则的排序,选择Comparator接口更合适。
(文章略显粗糙,若有错误,烦请批评指正!)