一種情況是集合類本身自帶排序功能,如前面說過的TreeSet
禽炬、SortedSet
荐吵、SortedMap
等菇篡,另一種就是本身不帶排序功能鹊漠,我們通過為需要排序的類實(shí)現(xiàn)Comparable
或者Comparator
接口來實(shí)現(xiàn)廊散。
綜述:
Comparable和Comparator都是用來實(shí)現(xiàn)集合中元素的比較由桌、排序的偿渡。
- Comparable是在集合內(nèi)部定義的方法實(shí)現(xiàn)的排序,位于java.lang下岖是。
- Comparator是在集合外部實(shí)現(xiàn)的排序帮毁,位于java.util下。
Comparable是一個(gè)對(duì)象本身就已經(jīng)支持自比較所需要實(shí)現(xiàn)的接口豺撑,如String烈疚、Integer自己就實(shí)現(xiàn)了Comparable接口,可完成比較大小操作聪轿。自定義類要在加入list容器中后能夠排序爷肝,也可以實(shí)現(xiàn)Comparable接口,在用Collections類的sort方法排序時(shí)若不指定Comparator屹电,那就以自然順序排序阶剑。所謂自然順序就是實(shí)現(xiàn)Comparable接口設(shè)定的排序方式。
Comparator是一個(gè)專用的比較器危号,當(dāng)這個(gè)對(duì)象不支持自比較或者自比較函數(shù)不能滿足要求時(shí)牧愁,可寫一個(gè)比較器來完成兩個(gè)對(duì)象之間大小的比較。Comparator體現(xiàn)了一種策略模式(strategy design pattern)外莲,就是不改變對(duì)象自身猪半,而用一個(gè)策略對(duì)象(strategy object)來改變它的行為兔朦。
總而言之Comparable是自已完成比較,Comparator是外部程序?qū)崿F(xiàn)比較磨确。
Comparator 和 Comparable區(qū)別與聯(lián)系
- a. Comparator 和 Comparable 相同的地方
他們都是java的一個(gè)接口, 并且是用來對(duì)自定義的class比較大小的,
什么是自定義class: 如 public class Person{ String name; int age }.
當(dāng)我們有這么一個(gè)personList
,里面包含了person1, person2, persion3.....
, 我們用Collections.sort( personList )
, 是得不到預(yù)期的結(jié)果的.
這時(shí)肯定有人要問, 那為什么可以排序一個(gè)字符串list呢:
如 StringList{"hello1" , "hello3" , "hello2"}
, Collections.sort( stringList )
能夠得到正確的排序, 那是因?yàn)?code>String 這個(gè)對(duì)象已經(jīng)幫我們實(shí)現(xiàn)了 Comparable
接口 , 所以我們的 Person
如果想排序, 也要實(shí)現(xiàn)一個(gè)比較器Comparable
接口沽甥。
- b. Comparator 和 Comparable 的區(qū)別
Comparable
Comparable 定義在 Person類的內(nèi)部:
public class Persion implements Comparable {..比較Person的大小..}
,
因?yàn)橐呀?jīng)實(shí)現(xiàn)了比較器,那么我們的Person現(xiàn)在是一個(gè)可以比較大小的對(duì)象了,它的比較功能和String完全一樣,可以隨時(shí)隨地的拿來
比較大小,因?yàn)镻erson現(xiàn)在自身就是有大小之分的。Collections.sort(personList)
可以得到正確的結(jié)果乏奥。
Comparator
Comparator 是定義在Person的外部的, 此時(shí)我們的Person類的結(jié)構(gòu)不需要有任何變化,如
public class Person{ String name; int age }
,
然后我們另外定義一個(gè)比較器:
public PersonComparator implements Comparator() {..比較Person的大小..}
,
在PersonComparator
里面實(shí)現(xiàn)了怎么比較兩個(gè)Person的大小. 所以,用這種方法,當(dāng)我們要對(duì)一個(gè)personList
進(jìn)行排序的時(shí)候, 我們除了了要傳遞personList
過去, 還需要把PersonComparator
傳遞過去,因?yàn)樵趺幢容^Person
的大小是在PersonComparator
里面實(shí)現(xiàn)的, 如:
Collections.sort( personList , new PersonComparator() ).
- c. Comparator 和 Comparable 的實(shí)例
Comparable:
實(shí)現(xiàn)Comparable接口要覆蓋compareTo方法, 在compareTo方法里面實(shí)現(xiàn)比較:
public class Person implements Comparable {
String name;
int age
public int compareTo(Person another) {
int i = 0;
i = name.compareTo(another.name); // 使用字符串的比較
if(i == 0) { // 如果名字一樣,比較年齡, 返回比較年齡結(jié)果
return age - another.age;
} else {
return i; // 名字不一樣, 返回比較名字的結(jié)果.
}
}
}
這時(shí)我們可以直接用 Collections.sort( personList ) 對(duì)其排序了.
Comparator:
實(shí)現(xiàn)Comparator需要覆蓋 compare 方法:
public class Person{
String name;
int age
}
class PersonComparator implements Comparator {
public int compare(Person one, Person another) {
int i = 0;
i = one.name.compareTo(another.name); // 使用字符串的比較
if(i == 0) { // 如果名字一樣,比較年齡,返回比較年齡結(jié)果
return one.age - another.age;
} else {
return i; // 名字不一樣, 返回比較名字的結(jié)果.
}
}
}
Collections.sort( personList , new PersonComparator())
可以對(duì)其排序
-
d:總結(jié)
兩種方法各有優(yōu)劣, 用Comparable 簡(jiǎn)單, 只要實(shí)現(xiàn)Comparable 接口的對(duì)象直接就成為一個(gè)可以比較的對(duì)象,但是需要修改源代碼;
用Comparator 的好處是不需要修改源代碼, 而是另外實(shí)現(xiàn)一個(gè)比較器, 當(dāng)某個(gè)自定義的對(duì)象需要作比較的時(shí)候,把比較器和對(duì)象一起傳遞過去就可以比大小了, 并且在Comparator 里面用戶可以自己實(shí)現(xiàn)復(fù)雜的可以通用的邏輯,使其可以匹配一些比較簡(jiǎn)單的對(duì)象,那樣就可以節(jié)省很多重復(fù)勞動(dòng)了摆舟。