我家开了个小卖店,为了实现数字化管理,我准备写个后台程序来对所有货物进行管理。首先定义了这个实体类,这个类就是“货物”类,num指的是他的编号,s指他的名称或描述,data指他的进货日期。
public class Goods {
int num;
String s;
Date date;
public Goods(int num, String s, Date date) {
this.num = num;
this.s = s;
this.date = date;
}
//getter setter
}
目前有一个需求,就是对所有货物进行排序。首先我想到了一个办法,就是直接实现Comparable接口,再实现接口定义的方法,在方法中完成货物的比较逻辑,虽然这样并不符合“开闭原则”,但我还是这么干了,于是这个类就变成了现在这个样子
public class Goods implements Comparable<Goods> {
int num;
String s;
Date date;
public Goods(int num, String s, Date date) {
this.num = num;
this.s = s;
this.date = date;
}
@Override
public int compareTo(Goods o) {
if (this.num>o.num)return 1;
else if (this.num==o.num) return 0;
else return -1;
}
//getter setter
}
看一下测试类
public class Main {
public static void main(String[] args) {
Goods g1=new Goods(1,"可乐",new Date(System.currentTimeMillis()));
Goods g2=new Goods(2,"面包",new Date(System.currentTimeMillis()+1000));
Goods[] goodss = {g2,g1};
Arrays.sort(goodss);
}
}
比较逻辑中比较的是货物的编号,g1比g2大,则返回1,小则返回-1,否则返回0;完成了这个比较逻辑,就可以进行排序了,简单调用Arrays.sort()就可以完美完成货物的排序。Arrays.sort内部调用了如下代码
if (length < INSERTIONSORT_THRESHOLD) {
for (int i=low; i<high; i++)
for (int j=i; j>low &&
((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
swap(dest, j, j-1);
return;
}
可以看到我们实现的方法compareTo()的调用,dest就是我们传入的goodss。就在我庆幸完成了任务时,我妈忽然嚷到“按编号排序有个啥子用啊???!!你是不是傻呀,进货日期赶紧改!!”哎,软件工程师(我就喜欢这么叫自己,傲娇脸)最烦的就是该需求了,但在老娘面前还是没脾气(说的好像在老板面前敢有脾气似的…)。于是我赶忙把compareTo中的比较对象换成了进货日期,完成任务后进入了“每日三省吾码”环节,这么写对嘛?还能怎样写?哪样写好呢?在思考一秒钟之后,嗯,还不行,哪天老娘又要按编号排,哪哪天又要改回来,我岂不是还得改来改去,于是乎,第二位主角登场Comparator
public class GoodsNumCompartor implements Comparator<Goods> {
@Override
public int compare(Goods o1, Goods o2) {
if (o1.getNum()>o2.getNum())return 1;
else if(o1.getNum()==o2.getNum())return 0;
else return -1;
}
}
public class GoodsDateCompartor implements Comparator<Goods> {
@Override
public int compare(Goods o1, Goods o2) {
return o1.getDate().compareTo(o2.getDate());
}
}
定义了两个比较器,以后需要用什么元素进行排序,就传入对应的比较器就可以了
Arrays.sort(goodss,new GoodsDateCompartor());
Arrays.sort(goodss,new GoodsNumCompartor());
源码中会调用我们的比较器
if (length < INSERTIONSORT_THRESHOLD) {
for (int i=low; i<high; i++)
for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--)
swap(dest, j, j-1);
return;
}
c就是我们传入的比较器,从起妈妈不会再难为我,老板不会再难为你。
实现comparable接口或定义一个比较器都可实现自定义对象的比较,不同的是,comparable需要修改原本的类信息来加入比较的逻辑;而比较器的方式将类本身的定义和类比较的定义进行了分离,耦合性降低了,灵活性增加了,而且通过增加比价器,我们可以增加多种比较方式。