Comparable接口的使用
Java中所有的compareTo方法都源于一个接口,那就是Comparable。这个接口只有一个方法,那就是CompareTo。所有想要具有比较功能的类,都建议实现这个接口,而非是自己定义这个功能,这是面向对象的概念(将具有相同功能的事物抽象到一个共同的类或接口),并且为了多态也建议通过实现接口来进行向上转型,通过接口来操作具体实现,这也是面向接口编程要求我们做的。
Java中要比较对象的大小或者要对对象的集合进行排序,需要通过比较这些对象的某些属性的大小来确定它们之间的大小关系。
一般,Java中通过接口实现两个对象的比较,比较常用就是Comparable接口和Comparator接口。首先类要实现接口,并且使用泛型规定要进行比较的对象所属的类,然后类实现了接口后,还需要实现接口定义的比较方法(compareTo方法或者compare方法),在这些方法中传入需要比较大小的另一个对象,通过选定的成员变量与之比较,如果大于则返回1,小于返回-1,相等返回0。
Comparable<T>接口对集合排序
此接口强行对实现它的每个类的对象进行整体排序。此排序被称为该类的自然排序 ,类的 compareTo方法被称为它的自然比较方法 。实现此接口的对象列表(和数组)可以通过 Collections.sort(和 Arrays.sort )进行自动排序。实现此接口的对象可以用作有序映射表中的键或有序集合中的元素,无需指定比较器。
实现什么方法
int compareTo(T o)
比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
参数: o - 要比较的对象。
返回:负整数、零或正整数,根据此对象是小于、等于还是大于指定对象。
public void test1(){
Integer i1 = 3;
Integer i2 = 7;
System.out.println(i2.compareTo(i1));//1
}
抛出:ClassCastException - 如果指定对象的类型不允许它与此对象进行比较。
public class Advice implements Serializable,Comparable<Advice> {
private static final long serialVersionUID = 6674013991838914395L;
private String adviceId;
private String profile;
private String content;
private String oriLink;
private String newsDate;
private String commentTotal;
private String duration;
private String createTime;
public String getAdviceId() {
return adviceId;
}
public String getNewsDate() {
return newsDate;
}
public void setNewsDate(String newsDate) {
this.newsDate = newsDate;
}
public String getDuration() {
return duration;
}
public void setDuration(String duration) {
this.duration = duration;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
@Override
public int compareTo(Advice ca) {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
try {
return df.parse(ca.getNewsDate()).compareTo(df.parse(this.getNewsDate()));
} catch (ParseException e) {
return 0;
}
}
}
后台对返回的集合调用Collection.sort方法进行排序
List<Advice> dataList =AdviceMapper.getAdviceById(columnId,companyId);
Collections.sort(dataList);
这样就可以实现,如果其他条件都相同的情况下,按照日期进行倒序排列
多个字段的比较,常常要在其他情况都相同的情况下,再进行排序
public class ConsumInfo implements Comparable<ConsumInfo> {
private int uid;
private String name;
private double price;
private Date datetime;
@Override
public int compareTo(ConsumInfo o) {
//首先比较price,如果price相同,则比较uid
if(price < o.price){
return -1;
}
if(price > o.price){
return 1;
}
if(price == o.price){
if(uid < o.uid){
return -1;
}
if(uid > o.uid){
return 1;
}
}
return 0;
}
}
public static void main(String[] args) {
ConsumInfo consumInfo1 = new ConsumInfo(100, "consumInfo1", 400.0,new Date());
ConsumInfo consumInfo2 = new ConsumInfo(200, "consumInfo1", 200.0,new Date());
List<ConsumInfo> list = new ArrayList<ConsumInfo>();
list.add(consumInfo1);
list.add(consumInfo2);
list.add(consumInfo3);
list.add(consumInfo4);
list.add(consumInfo5);
list.add(consumInfo6);
list.add(consumInfo7);
list.add(consumInfo8);
System.out.println("排序前:");
//排序前
for(ConsumInfo consumInfo : list ){
System.out.println(consumInfo);
}
Collections.sort(list);//排序
System.out.println("排序后:");
//排序后
for(ConsumInfo consumInfo :list){
System.out.println(consumInfo);
}
}
}
String和Integer对于compareTo()的实现
String和Integer这两个类都实现了Comparable接口,都对compareTo方法进行了实现,下面我们通过源码来看一下它们各自对于该方法的具体实现:
private final char value[];//String的底层是字符数组 a.compareTo(b)
public int compareTo(String anotherString) {
int len1 = value.length;//获取调用该方法的字符串的长度a
int len2 = anotherString.value.length;//获取比较字符串的长度b
int lim = Math.min(len1, len2);//(a <= b) ? a : b; min底层代码 这句代码是为了获取较短的字符串的长度
char v1[] = value; //创建两个字符数组,分别指向这两个字符串的所在
char v2[] = anotherString.value;
//循环比较,循环次数,是较短的字符串的长度,如果用较长的字符串的长度,那么会出现nullPointException
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
//比较相对应索引的元素,如果元素不同则比较返回中间差距的顺序,如果相等,那么就继续循环比较
if (c1 != c2) {
return c1 - c2;//字符对应的Unicode码表中的数字,这也就是为什么说String是按照字典书序比较的,如a比b靠前,那么a对应的数字比b小,相减返回负数,差多少顺序,就返回多少
}
k++;
}
//如果两个字符串的长度不同,其它都相同,那么返回的就是长度的差距了
return len1 - len2;
}
我们可以看到String对于compareTo的实现就是依据Unicode码表中字符对应的数字来判断的,返回的是字符串长度差或者是字符间在码表上的差距,依据具体情况,返回也不同.下面我们看看Integer的compareTo();
//Integer的compareTo方法,底层依据的是compare方法,这个方法是Comparator接口的一个方法
public int compareTo(Integer anotherInteger) {
//实际上Integer的比较是通过Integer中包括的整数来比较的
return compare(this.value, anotherInteger.value);
}
public static int compare(int x, int y) {//a.compateTo(b)
//如果a比b小,那么返回-1,相等就是0,否则就是1
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
没有实现Comparable接口的,可以通过Comparator实现排序
1 Person[] p = new Person[]{new Person("zhangsan",22),new Person("wangwu",11),new Person("lisi",33)};
2 Arrays.sort(p,new Comparator<Person>() {
3 @Override
4 public int compare(Person o1, Person o2) {
5 if(o1 == null || o2 == null){
6 return 0;
7 }
8 return o1.getPage()-o2.getPage();
9 }
10 });
11 System.out.println(Arrays.toString(p));