详解Java中Comparable和Comparator接口的区别
详解Java中Comparable和Comparator接口的区别
本文要来详细分析一下Java中Comparable和Comparator接口的区别,两者都有比较的功能,那么究竟有什么区别呢,感兴趣的Java开发者继续看下去吧。
Comparable简介
Comparable是排序接口。
若一个类实现了Comparable接口,就意味着“该类支持排序”。 即然实现Comparable接口的类支持排序,假设现在存在“实现Comparable接口的类的对象的List列表(或数组)”,则该List列表(或数组)可以通过Collections.sort(或Arrays.sort)进行排序。
此外,“实现Comparable接口的类的对象”可以用作“有序映射(如TreeMap)”中的键或“有序集合(TreeSet)”中的元素,而不需要指定比较器。
Comparable定义
Comparable接口仅仅只包括一个函数,它的定义如下:
packagejava.lang; importjava.util.*; publicinterfaceComparable{ publicintcompareTo(To); }
说明:
假设我们通过x.compareTo(y)来“比较x和y的大小”。若返回“负数”,意味着“x比y小”;返回“零”,意味着“x等于y”;返回“正数”,意味着“x大于y”。
Comparator简介
Comparator是比较器接口。
我们若需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口);那么,我们可以建立一个“该类的比较器”来进行排序。这个“比较器”只需要实现Comparator接口即可。
也就是说,我们可以通过“实现Comparator类来新建一个比较器”,然后通过该比较器对类进行排序。
Comparator定义
Comparator接口仅仅只包括两个个函数,它的定义如下:
packagejava.util; publicinterfaceComparator{ intcompare(To1,To2); booleanequals(Objectobj); }
说明:
(01)若一个类要实现Comparator接口:它一定要实现compareTo(To1,To2)函数,但可以不实现equals(Objectobj)函数。
为什么可以不实现equals(Objectobj)函数呢?因为任何类,默认都是已经实现了equals(Objectobj)的。Java中的一切类都是继承于java.lang.Object,在Object.java中实现了equals(Objectobj)函数;所以,其它所有的类也相当于都实现了该函数。
(02)intcompare(To1,To2)是“比较o1和o2的大小”。返回“负数”,意味着“o1比o2小”;返回“零”,意味着“o1等于o2”;返回“正数”,意味着“o1大于o2”。
Comparator和Comparable比较
Comparable是排序接口;若一个类实现了Comparable接口,就意味着“该类支持排序”。
而Comparator是比较器;我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。
我们不难发现:Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。
我们通过一个测试程序来对这两个接口进行说明。源码如下:
importjava.util.*;
importjava.lang.Comparable;
/**
*@desc"Comparator"和“Comparable”的比较程序。
*(01)"Comparable"
*它是一个排序接口,只包含一个函数compareTo()。
*一个类实现了Comparable接口,就意味着“该类本身支持排序”,它可以直接通过Arrays.sort()或Collections.sort()进行排序。
*(02)"Comparator"
*它是一个比较器接口,包括两个函数:compare()和equals()。
*一个类实现了Comparator接口,那么它就是一个“比较器”。其它的类,可以根据该比较器去排序。
*
*综上所述:Comparable是内部比较器,而Comparator是外部比较器。
*一个类本身实现了Comparable比较器,就意味着它本身支持排序;若它本身没实现Comparable,也可以通过外部比较器Comparator进行排序。
*/
publicclassCompareComparatorAndComparableTest{
publicstaticvoidmain(String[]args){
//新建ArrayList(动态数组)
ArrayListlist=newArrayList();
//添加对象到ArrayList中
list.add(newPerson("ccc",20));
list.add(newPerson("AAA",30));
list.add(newPerson("bbb",10));
list.add(newPerson("ddd",40));
//打印list的原始序列
System.out.printf("Originalsort,list:%s\n",list);
//对list进行排序
//这里会根据“Person实现的Comparable接口”进行排序,即会根据“name”进行排序
Collections.sort(list);
System.out.printf("Namesort,list:%s\n",list);
//通过“比较器(AscAgeComparator)”,对list进行排序
//AscAgeComparator的排序方式是:根据“age”的升序排序
Collections.sort(list,newAscAgeComparator());
System.out.printf("Asc(age)sort,list:%s\n",list);
//通过“比较器(DescAgeComparator)”,对list进行排序
//DescAgeComparator的排序方式是:根据“age”的降序排序
Collections.sort(list,newDescAgeComparator());
System.out.printf("Desc(age)sort,list:%s\n",list);
//判断两个person是否相等
testEquals();
}
/**
*@desc测试两个Person比较是否相等。
*由于Person实现了equals()函数:若两person的age、name都相等,则认为这两个person相等。
*所以,这里的p1和p2相等。
*
*TODO:若去掉Person中的equals()函数,则p1不等于p2
*/
privatestaticvoidtestEquals(){
Personp1=newPerson("eee",100);
Personp2=newPerson("eee",100);
if(p1.equals(p2)){
System.out.printf("%sEQUAL%s\n",p1,p2);
}else{
System.out.printf("%sNOTEQUAL%s\n",p1,p2);
}
}
/**
*@descPerson类。
*Person实现了Comparable接口,这意味着Person本身支持排序
*/
privatestaticclassPersonimplementsComparable{
intage;
Stringname;
publicPerson(Stringname,intage){
this.name=name;
this.age=age;
}
publicStringgetName(){
returnname;
}
publicintgetAge(){
returnage;
}
publicStringtoString(){
returnname+"-"+age;
}
/**
*比较两个Person是否相等:若它们的name和age都相等,则认为它们相等
*/
booleanequals(Personperson){
if(this.age==person.age&&this.name==person.name)
returntrue;
returnfalse;
}
/**
*@desc实现“Comparable”的接口,即重写compareTo函数。
*这里是通过“person的名字”进行比较的
*/
@Override
publicintcompareTo(Personperson){
returnname.compareTo(person.name);
//returnthis.name-person.name;
}
}
/**
*@descAscAgeComparator比较器
*它是“Person的age的升序比较器”
*/
privatestaticclassAscAgeComparatorimplementsComparator{
@Override
publicintcompare(Personp1,Personp2){
returnp1.getAge()-p2.getAge();
}
}
/**
*@descDescAgeComparator比较器
*它是“Person的age的升序比较器”
*/
privatestaticclassDescAgeComparatorimplementsComparator{
@Override
publicintcompare(Personp1,Personp2){
returnp2.getAge()-p1.getAge();
}
}
}
下面对这个程序进行说明。
a)Person类定义。如下:
privatestaticclassPersonimplementsComparable{ intage; Stringname; ... /** *@desc实现“Comparable ”的接口,即重写compareTo函数。 *这里是通过“person的名字”进行比较的 */ @Override publicintcompareTo(Personperson){ returnname.compareTo(person.name); //returnthis.name-person.name; } }
说明:
(01)Person类代表一个人,Persong类中有两个属性:age(年纪)和name“人名”。
(02)Person类实现了Comparable接口,因此它能被排序。
b)在main()中,我们创建了Person的List数组(list)。如下:
//新建ArrayList(动态数组) ArrayListlist=newArrayList (); //添加对象到ArrayList中 list.add(newPerson("ccc",20)); list.add(newPerson("AAA",30)); list.add(newPerson("bbb",10)); list.add(newPerson("ddd",40));
c)接着,我们打印出list的全部元素。如下:
//打印list的原始序列
System.out.printf("Originalsort,list:%s\n",list);
d)然后,我们通过Collections的sort()函数,对list进行排序。
由于Person实现了Comparable接口,因此通过sort()排序时,会根据Person支持的排序方式,即compareTo(Personperson)所定义的规则进行排序。如下:
//对list进行排序 //这里会根据“Person实现的Comparable接口”进行排序,即会根据“name”进行排序 Collections.sort(list); System.out.printf("Namesort,list:%s\n",list);
e)对比Comparable和Comparator
我们定义了两个比较器AscAgeComparator和DescAgeComparator,来分别对Person进行升序和降低排序。
e.1)AscAgeComparator比较器
它是将Person按照age进行升序排序。代码如下:
/** *@descAscAgeComparator比较器 *它是“Person的age的升序比较器” */ privatestaticclassAscAgeComparatorimplementsComparator{ @Override publicintcompare(Personp1,Personp2){ returnp1.getAge()-p2.getAge(); } }
e.2)DescAgeComparator比较器
它是将Person按照age进行降序排序。代码如下:
/** *@descDescAgeComparator比较器 *它是“Person的age的升序比较器” */ privatestaticclassDescAgeComparatorimplementsComparator{ @Override publicintcompare(Personp1,Personp2){ returnp2.getAge()-p1.getAge(); } }
f)运行结果
运行程序,输出如下:
Originalsort,list:[ccc-20,AAA-30,bbb-10,ddd-40] Namesort,list:[AAA-30,bbb-10,ccc-20,ddd-40] Asc(age)sort,list:[bbb-10,ccc-20,AAA-30,ddd-40] Desc(age)sort,list:[ddd-40,AAA-30,ccc-20,bbb-10] eee-100EQUALeee-100
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!