在jdk中,封装了Comparable和Comparator接口,但是这两个接口的作用是干嘛的呢?在这里做下简单的介绍。
在平时的练习中,想必大家都做过排序的操作吧?但对排序的操作如果写死在程序里面的话,那在对不同类型的数据进行排序,如int、float甚至是自己新建的类的话,是不是就要重载好几个排序的方法呢?这样的方式肯定是不合适的。
那么这个时候我们就可以新建一个Comparable接口,在这个接口中建立一个comparaTo()方法,表示是进行比较的操作,具体比较的方法,在具体的实现该接口的类中操作,如下
public int comparaTo(Object o); |
假如现在想对猫Cat这个类进行排序,那么在Cat这个类中就需要实现Comparable接口,并覆写好方法,当然在这个类中会存在一些属性,如name,age,用于排序。
范例:Cat中覆写comparaTo()方法
@Override public int comparaTo(Object o) { if(o instanceof Cat){ Cat c=(Cat)o; //强制转换 if(this.age>c.getAge()) return 1; else if(this.age>c.getAge()) return -1; else return 0; } return -100; } |
在上面的操作中,一般是先要判断o是否为Cat的对象,否则的话应该抛出异常,表示不是同一个对象,不能进行比较。在这里就直接返回-100,进行标记即可。
如果要比较的对象是Cat对象的话,那么就把o强制转换成Cat对象,然后根据age进行排序,返回1表示当前Cat的对象(this)的age大于传递进来的对象(o)的age。返回-1表示小于,0表示等于。
那么在具体的在具体的排序类中就可以用一下代码进行比较了
public static void sort(Object[] c) { for(int i=c.length;i>0;i--){ for(int j=0;j<i-1;j++){ if(c[j].comparaTo(c[j+1])>0){ //大于,表示要进行交换 swap(c,j,j+1); //进行交换 } } } } |
这样就可以进行根据Cat的age进行排序了。
只是大家应该会发现,这个时候Cat类中的comparaTo()方法是写死的,也就是说只能通过Cat的age属性进行排序,那这样拓展性是很差的,如果要是想用其他属性进行排序的话,是否就意味着要去修改comparaTo()方法呢?这样的操作肯定是不推崇的。
所以这个时候就可以用到Comparator接口了,在接口中建立一个compara()方法
/** * 根据对象的属性进行比较,即生成自己的比较器 * @param o1 * @param o2 * @return */ int compare(Object o1,Object o2); //在interface中默认的修饰符是public |
然后新建一个java类,表示排序的策略,比较创建一个CatAgeCompartor类,表示一个策略器,这个策略器是根据Cat的age进行排序的。
范例:编写CatAgeCompartor类,覆写compara()方法
@Override /** * 定义自己的比较器,这里用age */ public int compare(Object o1, Object o2) { Cat c1 = (Cat) o1; // 强制转换 Cat c2 = (Cat) o2; // 强制转换 if(c1.getAge()>c2.getAge())return 1; else if(c1.getAge()<c2.getAge()) return -1; else return 0; } |
在这里的方法表示是根据age进行排序,就不加以说明了。所以这个时候在Cat中的comparaTo()方法就可以灵活的使用了。进行如下操作:
private Comparator comparator=new CatAgeComparator(); //实例化猫自己的比较器 @Override public int comparaTo(Object o) { return comparable.compare(this, o); } |
这样就可以根据Cat的age进行排序了,这样拓展性就强多了。比如现在Cat这个类又有一个weight属性,然后你想根据weight进行排序的时候,只需要创建一个策略器CatWeightCompartor,记得实现Comparator接口,覆写对应的方法即可。这样是不是就方便多了呢?
其实jdk已经把这些操作全部都实现好了,所以我们只需要进行使用就行了,当想进行排序的时候,调用jdk自带的sort()方法就可以了,不过如果是对自己新建的类进行排序的话,那么记得实现类要实现Comparable接口,策略器要实现Comparator接口,而且jdk封装的这些方法中都使用了泛型,那这个时候在实现接口的实现把要进行比较的类传递进行,后续的操作就不再需要进行强制转换了。
代码:
Comparable接口
public interface Comparable { /** * 表示跟一个对象进行比较,返回int类型的值, * @param o 传递的object对象 * @return */ public int comparaTo(Object o); } |
Comparator接口
public interface Comparator { /** * 根据对象的属性进行比较,即生成自己的比较器 */ int compare(Object o1,Object o2); //在interface中默认的修饰符是public } |
CatAgeComparator类
public class CatAgeComparator implements Comparator { @Override /** * 定义自己的比较器,这里用age */ public int compare(Object o1, Object o2) { Cat c1 = (Cat) o1; // 强制转换 Cat c2 = (Cat) o2; // 强制转换 if(c1.getAge()>c2.getAge())return 1; else if(c1.getAge()<c2.getAge()) return -1; else return 0; } } |
Cat类关键代码
public class Cat implements Comparable{ private String name; private int age; private Comparator comparator=new CatAgeComparable(); //实例化猫自己的比较器 //省略getter、setter、toString public Cat(String name, int age) { super(); this.name = name; this.age = age; } @Override /** * 进行猫自己的比较 */ public int comparaTo(Object o) { return comparator.compare(this, o); } } |
Sort类关键代码
public static void sort(Comparable[] c) { for(int i=c.length;i>0;i--){ for(int j=0;j<i-1;j++){ if(c[j].comparaTo(c[j+1])>0){ //大于,表示要进行交换 swap(c,j,j+1); //进行交换 } } } } |
测试类Test
Cat c[]={new Cat("小花12",4),new Cat("小白",1),new Cat("小黑仔",3)}; ObjectSort.sort(c); //排序 ObjectSort.print(c); //打印 |