Comparable接口
在java中,如果一个类要支持排序功能,一个方法就是要实现java.lang.Comparable接口,并实现其中的public int compareTo(object);方法。
因为如果两个对象要进行排序,首先要进行比较大小。而这个接口中的compareTo(object)方法就是比较大小的规则。在需要排序的类中自定义比较规则。
例如我有一个Student类,有很多Student的实例(也就是对象)。要怎么来排序呢?是根据年龄?学号?还是考试分数呢?这就要实现Comparable里的compareTo方法了。
通过a.compareTo(b)来比较a和b的大小,如果返回负数,则a<b;如果返回0,则a=b;如果返回正数,则a>b;
例子:这里实现一个Student类,通过年龄来比较大小。public class Student implements Comparable<Student>{
private String name; private int age; private double scores; @Override public int compareTo(Student o) { //this代表当前对象,如:a.compareTo(b);这里的this就是a,b就是传过来的参数o; return this.age-o.age; //上面的例子中是比较年龄,其实也可以实现比较姓名的首字母排列顺序,当然这里需要是英文。 //如下: /* if(this.name.charAt(0)>o.name.charAt(0)) { return -1; }else if(this.name.charAt(0)<o.name.charAt(0)){ return 1; }else { return 0; } //这里比较姓名首字母还有很多地方没考虑,这里只是为了演示可以自定义排序方式。 */ }
//省略getter/setter和toString的实现。。。。。。。。。。。。。。。。。。。。。。。。。 }
Comparator接口
这个是比较器接口,与上面的commparable差不多用来比较和排序的。如上面的Student类,我们定义的时候就已经给他实现了比较接口了,这样他的实例对象就可以排序了。
但是如果Student一上来定义的人没有实现这个接口,或者我们要排序的对象的类没有实现Comparable接口,要怎么排序呢?
这时候就用Comaparator就可以了,实现其int compare(T o1, T o2);方法,这方法返回负数,则o1<o1;返回0,则o1=o2;返回正数,则o1>o2。
例子:这次我们的Student类不实现Commparable接口了,就直接是Student1类。
public class Student1 { private String name; private int age; private double scores; //省略getter/setter和toString的实现 }
这时候还是想把Student的实例对象进行比较进而排序要怎么做?当然是再实现一个比较器了,并实现其int compare(T o1, T o2);方法,代码如下。
public class StudentComparator implements Comparator<Student1>{ @Override public int compare(Student1 o1, Student1 o2) { //跟之前用Comparable接口是不是一样 return o1.getAge()-o2.getAge(); } }
当然如果这个比较器只用一次的话,也可以使用匿名类的方法直接写,而不用再新建一个java文件再新建一个类了,如下,跟上面是一样。
public class Test { public static void main(String[] args) { //这里直接在main方法中实现了比较的方法,因为只使用这一次,在新建个java文件比较烦,所以可以直接这样写。 //需要排序的hi后用这个myComparator就好 Comparator myComparator=new Comparator<Student1>(){ @Override public int compare(Student1 o1, Student1 o2) { //跟之前的一样 return o1.getAge()-o2.getAge(); } }; } }
使用上面的类进行排序/对比实验
为了检测这两个比较的实现有没有成功,我们使用Collections这个工具类的sort()方法来测试一下。
Collections里的这个sort()排序方法刚好能满足测试上面两个例子的条件。接口源码如下:
这个排序方法sort(list)传入的list中存的对象必须是实现了Comparable接口的对象。
这个排序方法sort(list,comparator);中需要传入两个参数,一个就是需要排序的list,第二个就是对比器的实现。对应上面实现的StudentComparator。
测试:Comparable接口实现的排序
public class Test1 { public static void main(String[] args) { //为了测试方便。这里还实现了一个有三个参数的构造器,跟getter/setter和toString一样,上面的代码中没有体现出来。 List<Student> list=new ArrayList<>(); //不按年龄的顺序添加daolist中 list.add(new Student("张三",18,99)); list.add(new Student("老白",23,90)); list.add(new Student("大嘴",22,50)); list.add(new Student("小郭",18,70)); System.out.println(list); //输出: //[Student [name=张三, age=18, scores=99.0], Student [name=老白, age=23, scores=90.0], Student [name=大嘴, age=22, scores=50.0], Student [name=小郭, age=18, scores=70.0]] //排序 Collections.sort(list); System.out.println(list); //输出: //[Student [name=张三, age=18, scores=99.0], Student [name=小郭, age=18, scores=70.0], Student [name=大嘴, age=22, scores=50.0], Student [name=老白, age=23, scores=90.0]] //上面的list中的Student原来没有按照年龄顺序排序,后来排好了。 } }
测试:Comparator接口实现的排序
public class Test2 { public static void main(String[] args) { //为了测试方便。这里还实现了一个有三个参数的构造器,跟getter/setter和toString一样,上面的代码中没有体现出来。 List<Student1> list=new ArrayList<>(); //不按年龄的顺序添加到list中 list.add(new Student1("张三",18,99)); list.add(new Student1("老白",23,90)); list.add(new Student1("大嘴",22,50)); list.add(new Student1("小郭",18,70)); //创建排序器对象 StudentComparator myComparator=new StudentComparator(); System.out.println(list); //输出: //[Student1 [name=张三, age=18, scores=99.0], Student1 [name=老白, age=23, scores=90.0], Student1 [name=大嘴, age=22, scores=50.0], Student1 [name=小郭, age=18, scores=70.0]] //排序 Collections.sort(list,myComparator); System.out.println(list); //输出: //[Student1 [name=张三, age=18, scores=99.0], Student1 [name=小郭, age=18, scores=70.0], Student1 [name=大嘴, age=22, scores=50.0], Student1 [name=老白, age=23, scores=90.0]] //哈哈一样的 } }
想知道排序的时候怎么用到我们实现的对比的,可以Debug跟一下,或者看一下源码,一下就明白了
end..............