Comparable<T>和Comparator<T>是Java中适用于不同情景下的用来对数据进行比较(排序)的两个接口。
情景:有一个存放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); } } }
运行结果:
情景:有一个存放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接口更合适。
(文章略显粗糙,若有错误,烦请批评指正!)