項目中經(jīng)常會遇到列表搜索查詢,大部分的查詢是可以通過sql語句來實現(xiàn)的,有些特殊的搜索排序sql則實現(xiàn)不了,例如中文排序。。
本文,先介紹Comparable 和Comparator兩個接口,以及它們的差異;接著,通過示例,對它們的使用方法進(jìn)行說明。
Comparable 簡介
Comparable 是排序接口。
若一個類實現(xiàn)了Comparable接口,就意味著“該類支持排序”。
即然實現(xiàn)Comparable接口的類支持排序,假設(shè)現(xiàn)在存在“實現(xiàn)Comparable接口的類的對象的List列表(或數(shù)組)”,則該List列表(或數(shù)組)可以通過
Collections.sort(或 Arrays.sort)進(jìn)行排序。
Comparable 定義
Comparable 接口僅僅只包括一個函數(shù),它的定義如下:
?? ? package java.lang;import java.util.*;
? ?? public interface Comparable {
? ? ? ? ? public int compareTo(T o);
????? }
說明:
假設(shè)我們通過 x.compareTo(y) 來“比較x和y的大小”。若返回“負(fù)數(shù)”,意味著“x比y小”;返回“零”,意味著“x等于y”;返回“正數(shù)”,意味著“x大于y”。
Comparator 簡介
Comparator 是比較器接口。
我們?nèi)粜枰刂颇硞€類的次序,而該類本身不支持排序(即沒有實現(xiàn)Comparable接口);那么,我們可以建立一個“該類的比較器”來進(jìn)行排序。這個“比較器”只需要實現(xiàn)Comparator接口即可。
也就是說,我們可以通過“實現(xiàn)Comparator類來新建一個比較器”,然后通過該比較器對類進(jìn)行排序。
Comparator 定義
Comparator 接口僅僅只包括兩個個函數(shù),它的定義如下:
??? package java.util;
??? public interface Comparator {
??? ? ? ? int? compare(T o1, T o2);? ?
??? ? ? ? boolean equals(Object obj);
??? }
說明:
(01) 若一個類要實現(xiàn)Comparator接口:它一定要實現(xiàn)compare(T o1, T o2) 函數(shù),但可以不實現(xiàn) equals(Object obj) 函數(shù)。
為什么可以不實現(xiàn)
equals(Object obj) 函數(shù)呢? 因為任何類,默認(rèn)都是已經(jīng)實現(xiàn)了equals(Object obj)的。
Java中的一切類都是繼承于java.lang.Object,在Object.java中實現(xiàn)了equals(Object
obj)函數(shù);所以,其它所有的類也相當(dāng)于都實現(xiàn)了該函數(shù)。
(02) int compare(T o1, T o2) 是“比較o1和o2的大小”。返回“負(fù)數(shù)”,意味著“o1比o2小”;返回“零”,意味著“o1等于o2”;返回“正數(shù)”,意味著“o1大于o2”。
Comparator 和 Comparable 比較
Comparable是排序接口;若一個類實現(xiàn)了Comparable接口,就意味著“該類支持排序”。
而Comparator是比較器;我們?nèi)粜枰刂颇硞€類的次序,可以建立一個“該類的比較器”來進(jìn)行排序。
我們不難發(fā)現(xiàn):Comparable相當(dāng)于“內(nèi)部比較器”,而Comparator相當(dāng)于“外部比較器”。
我們通過一個測試程序來對這兩個接口進(jìn)行說明。源碼如下:
import java.util.*;
import java.lang.Comparable;
/**
* @desc "Comparator"和“Comparable”的比較程序。
*? (01) "Comparable"
*? 它是一個排序接口,只包含一個函數(shù)compareTo()。
*? 一個類實現(xiàn)了Comparable接口,就意味著“該類本身支持排序”,它可以直接通過Arrays.sort() 或
Collections.sort()進(jìn)行排序。
*? (02) "Comparator"
*? 它是一個比較器接口,包括兩個函數(shù):compare() 和 equals()。
*? 一個類實現(xiàn)了Comparator接口,那么它就是一個“比較器”。其它的類,可以根據(jù)該比較器去排序。
*? 綜上所述:Comparable是內(nèi)部比較器,而Comparator是外部比較器。
*? 一個類本身實現(xiàn)了Comparable比較器,就意味著它本身支持排序;若它本身沒實現(xiàn)Comparable,也可以通過外部比較
器Comparator進(jìn)行排序。
*/
public class CompareComparatorAndComparableTest{??
?????????????????? public static void main(String[] args) {? ? ??
?????????????????????????? // 新建ArrayList(動態(tài)數(shù)組)? ? ??
????????????????????????? ArrayListlist = new ArrayList();? ? ??
???????????????????????? // 添加對象到ArrayList中? ? ??
????????????????????? ? list.add(new Person("ccc", 20));? ? ??
???????????????????????? list.add(new Person("AAA", 30));? ? ? ?
???????????????????????? list.add(new Person("bbb", 10));? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ?? list.add(new Person("ddd", 40));? ? ??
??????????????????????? // 打印list的原始序列? ? ? ?
????????????????????????? System.out.printf("Original? sort, list:%s\n", list);? ? ??
?????????????????????? // 對list進(jìn)行排序 ,這里會根據(jù)“Person實現(xiàn)的Comparable接口”進(jìn)行排序,即會根據(jù)“name”進(jìn)行排序
?????????????????????????? Collections.sort(list);
????????????????????????? System.out.printf("Name? ? ? sort, list:%s\n", list);
?????????????????????? // 通過“比較器(AscAgeComparator)”,對list進(jìn)行排序
?????????????????????? // AscAgeComparator的排序方式是:根據(jù)“age”的升序排序
????????????????????? Collections.sort(list, new AscAgeComparator());
????????????????????? System.out.printf("Asc(age)? sort, list:%s\n", list);
???????????????????? // 通過“比較器(DescAgeComparator)”,對list進(jìn)行排序
??????????????????? // DescAgeComparator的排序方式是:根據(jù)“age”的降序排序
???????????????????? Collections.sort(list, new DescAgeComparator());
????????????????????? System.out.printf("Desc(age) sort, list:%s\n", list);
???????????????????? // 判斷兩個person是否相等
?????????????????????? testEquals();
}
/**
* @desc 測試兩個Person比較是否相等。
*? 由于Person實現(xiàn)了equals()函數(shù):若兩person的age、name都相等,則認(rèn)為這兩個person相等。
*? 所以,這里的p1和p2相等。
*
*? TODO:若去掉Person中的equals()函數(shù),則p1不等于p2
*/
private static void testEquals() {
????????? Person p1 = new Person("eee", 100);
????????? Person p2 = new Person("eee", 100);
????????? if (p1.equals(p2)) {
???????????????? System.out.printf("%s EQUAL %s\n", p1, p2);
?????????? } else {
???????????????? System.out.printf("%s NOT EQUAL %s\n", p1, p2);
????????? }
}
/**? ? * @desc Person類。? ? *? ? ? Person實現(xiàn)了Comparable接口,這意味著Person本身支持排序? ? */??
private static class Person implements Comparable{? ? ?
? ? ? ? ? int age;? ? ? ?
???????? String name;? ? ??
???????? public Person(String name, int age) {? ? ? ? ? ?
?????????????????????????? this.name = name;? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ??? ? this.age = age;? ? ??
???????? }? ? ?
? ? ? ? public String getName() {? ? ? ? ??
????????????????? return name;? ? ??
????????? }? ? ? ?
?? ? ? public int getAge() {? ? ? ? ?
? ? ? ? ? ?? return age;? ? ??
? ? ?? }? ? ?
? ?? public String toString() {? ? ? ? ?
? ? ? ? ? ? ? return name + " - " +age;? ? ?
? ?? }? ? ??
?/**? ? ? ? * 比較兩個Person是否相等:若它們的name和age都相等,則認(rèn)為它們相等? ? ? ? */? ?
? ? ? ? boolean equals(Person person) {? ? ? ? ??
????????????? if (this.age == person.age && this.name == person.name)? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ?? return true;? ? ? ? ??
?????????????? return false;? ? ?
? }? ? ??
/**? ? ? ? * @desc 實現(xiàn) “Comparable” 的接口,即重寫compareTo函數(shù)。
*? 這里是通過“person的名字”進(jìn)行比較的
*/
@Override
public int compareTo(Person person) {
???????? return name.compareTo(person.name);
????????? //return this.name - person.name;
}
}
/**? ? * @desc AscAgeComparator比較器? ? *? ??
???????? 它是“Person的age的升序比較器”? ? */??
????? private static class AscAgeComparator implements Comparator{? ? ? ?
??????? @Override? ? ?
? ? ?? public int compare(Person p1, Person p2) {? ? ? ? ??
??????????? return p1.getAge() - p2.getAge();? ? ?
? ? ? ? ? }??
??? }??
??? /**? ? * @desc DescAgeComparator比較器? ? *? ?
? ? ? ? ? 它是“Person的age的升序比較器”? ? */?
?? private static class DescAgeComparator implements Comparator{
? ? ? ? ?? @Override
? ? ? ? ?? public int compare(Person p1, Person p2) {
? ? ? ? ? ? ? ? ? ? ? return p2.getAge() - p1.getAge();
???????????? }
??? }
}
下面對這個程序進(jìn)行說明。
???? a) Person類定義。如下:
?????? private static class Person implements Comparable{??
???????????????????????????? int age;? ? String name;? ? ? ? ...? ?
?????????? /**? ? ? * @desc 實現(xiàn) “Comparable” 的接口,即重寫compareTo函數(shù)。??
??????????????? *? 這里是通過“person的名字”進(jìn)行比較的? ? */?
? ? ? ? ? ? ? ? ?? @Override??
????????????????????? public int compareTo(Person person) {? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? return name.compareTo(person.name);? ? ??
?????????????????????????? //return this.name - person.name;?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }?
?????????????????????? }說明:(01) Person類代表一個人,Persong類中有兩個屬性:age(年紀(jì)) 和 name“人名”。
???????????????????????????? (02) Person類實現(xiàn)了Comparable接口,因此它能被排序。
???????????????????????????? b) 在main()中,我們創(chuàng)建了Person的List數(shù)組(list)。
?????????????????????????????? 如下:// 新建ArrayList(動態(tài)數(shù)組)ArrayListlist = new ArrayList();
??????????????????????????????????? // 添加對象到ArrayList中l(wèi)ist.add(new Person("ccc", 20));
??????????????????????????????????? list.add(new Person("AAA", 30));list.add(new Person("bbb", 10));
????????????????????????????????? list.add(new Person("ddd", 40));c)
?????????????????????????????? 接著,我們打印出list的全部元素。如下:
????????????????????????? // 打印list的原始序列System.out.printf("Original sort, list:%s\n", list);d) 然后,我們通過Collections的sort()函數(shù),對list進(jìn)行排序。由于Person實現(xiàn)了Comparable接口,因此通過sort()排序時,會根據(jù)Person支持的排序方式,即 compareTo(Person person) 所定義的規(guī)則進(jìn)行排序。如下:// 對list進(jìn)行排序// 這里會根據(jù)“Person實現(xiàn)的Comparable接口”進(jìn)行排序,即會根據(jù)“name”進(jìn)行排序??????????????????
??????????????????????????? Collections.sort(list);
????????????????????????????? System.out.printf("Name sort, list:%s\n", list);e)
????????????????????????????? 對比Comparable和Comparator我們定義了兩個比較器 AscAgeComparator 和 DescAgeComparator,來分別對Person進(jìn)行 升序 和 降低 排序。
???????????????????????????????? e.1) AscAgeComparator比較器它是將Person按照age進(jìn)行升序排序。代碼如下:
????????????????????????????????? /** * @desc AscAgeComparator比較器 * 它是“Person的age的升序比較器”?? */
???????????????????? private static class AscAgeComparator implements Comparator{??
??????????????????????????? @Override? ?
???????????????????????????? public int compare(Person p1, Person p2) {? ? ??
?????????????????????????????????? return p1.getAge() - p2.getAge();??
??????????????????????????????? }}
????????????????????????? e.2) DescAgeComparator比較器它是將Person按照age進(jìn)行降序排序。代碼如下:/** *
?????????????????????????????? @desc DescAgeComparator比較器 *? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 它是“Person的age的升序比較器” */
??? private static class DescAgeComparator implements Comparator{
???????????????? @Override
?????????????????? public int compare(Person p1, Person p2) {
????????????? ? ? ? ? ? ? return p2.getAge() - p1.getAge();
????????????? }
}