详解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
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!