一文搞清楚Java中Comparable和Comparator的區(qū)別
Java中的Comparable
和Comparator
都是用于集合排序的接口,但它們有明顯的區(qū)別。
很多人問(wèn)我,到底該用哪一個(gè),自己在使用時(shí)很疑惑?
對(duì)于這個(gè)問(wèn)題,沒(méi)有一定的規(guī)則來(lái)決定選擇哪一個(gè)更好,因?yàn)樗Q于具體情況以及開(kāi)發(fā)者的個(gè)人偏好。
如果你所需要排序的類(lèi)已經(jīng)實(shí)現(xiàn)了
Comparable
接口,那么你可以直接使用該類(lèi)默認(rèn)的比較規(guī)則進(jìn)行排序。否則,你可以考慮實(shí)現(xiàn)一個(gè)或多個(gè)Comparator
接口,并基于不同的比較規(guī)則對(duì)同一個(gè)類(lèi)進(jìn)行排序。在某些情況下,你可能會(huì)發(fā)現(xiàn)自己需要對(duì)同一個(gè)類(lèi)使用多個(gè)不同的比較規(guī)則進(jìn)行排序。在這種情況下,使用
Comparator
接口是一種更加靈活的選擇,因?yàn)槟憧梢愿鶕?jù)需要編寫(xiě)任意數(shù)量的比較器,并將它們與同一個(gè)類(lèi)的不同實(shí)例一起使用。在另一些情況下,你可能會(huì)發(fā)現(xiàn)自然排序已經(jīng)足夠滿(mǎn)足你的需求。如果你只需要對(duì)一個(gè)類(lèi)中的對(duì)象按照默認(rèn)的比較規(guī)則進(jìn)行排序,那么你可以直接實(shí)現(xiàn)
Comparable
接口。
在本文詳細(xì)介紹兩者前,我申明,在Java中,Comparable
和Comparator
都是非常有用的接口,能夠幫助開(kāi)發(fā)者輕松地對(duì)集合進(jìn)行排序,并根據(jù)特定的比較規(guī)則來(lái)確定排序順序。具體選擇哪一個(gè)接口,需要考慮多方面的因素,并且也要結(jié)合具體的需求和實(shí)際情況來(lái)進(jìn)行選擇。
1、Comparable
Comparable
是一個(gè)排序接口,它強(qiáng)制實(shí)現(xiàn)排序規(guī)則在類(lèi)本身定義,也就是說(shuō),如果一個(gè)類(lèi)實(shí)現(xiàn)了Comparable
接口,那么該類(lèi)的對(duì)象就可以進(jìn)行自然排序。自然排序即默認(rèn)排序,如數(shù)字的升序排序、字符串的字典序排序等。
實(shí)現(xiàn)Comparable
需要重寫(xiě)其中的compareTo
方法,該方法的返回值類(lèi)型為int,根據(jù)比較結(jié)果返回正整數(shù)、0或者負(fù)整數(shù),其含義如下:
- 返回正整數(shù):當(dāng)前對(duì)象大于目標(biāo)對(duì)象
- 返回0:當(dāng)前對(duì)象等于目標(biāo)對(duì)象
- 返回負(fù)整數(shù):當(dāng)前對(duì)象小于目標(biāo)對(duì)象
以下代碼示例展示了如何實(shí)現(xiàn)Comparable
接口:
public class Person implements Comparable<Person> { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public int compareTo(Person o) { return this.age - o.age; } // 省略getter/setter方法 }
在上述代碼中,Person
類(lèi)實(shí)現(xiàn)了Comparable
接口,并重寫(xiě)了其中的compareTo
方法,按照年齡大小進(jìn)行比較。這里的比較規(guī)則是年齡越小,優(yōu)先級(jí)越高。
使用Comparable
進(jìn)行排序時(shí),只需要對(duì)集合調(diào)用Collections.sort()
方法,因?yàn)樵摲椒ㄒ呀?jīng)內(nèi)置了對(duì)自然排序的支持。
List<Person> personList = new ArrayList<>(); personList.add(new Person("張三", 20)); personList.add(new Person("李四", 18)); personList.add(new Person("王五", 21)); Collections.sort(personList); System.out.println(personList);
運(yùn)行上述代碼,結(jié)果如下所示:
[Person{name='李四', age=18}, Person{name='張三', age=20}, Person{name='王五', age=21}]
2、Comparator
Comparator
是一個(gè)比較器接口,它可以為需要排序的類(lèi)提供多種不同的排序規(guī)則。與Comparable
不同的是,Comparator
實(shí)現(xiàn)的排序規(guī)則是在調(diào)用時(shí)才確定。
同樣需要重寫(xiě)其中的compare
方法,在方法中傳入兩個(gè)待比較的對(duì)象,并返回比較結(jié)果,含義和compareTo
方法相同。但是,需要注意的是,對(duì)于同一類(lèi)型的不同對(duì)象,不同的比較器實(shí)現(xiàn)可能會(huì)返回不同的比較結(jié)果。
以下代碼示例展示了如何使用Comparator
進(jìn)行排序:
public class PersonAgeComparator implements Comparator<Person> { @Override public int compare(Person o1, Person o2) { return o1.getAge() - o2.getAge(); } } List<Person> personList = new ArrayList<>(); personList.add(new Person("張三", 20)); personList.add(new Person("李四", 18)); personList.add(new Person("王五", 21)); Collections.sort(personList, new PersonAgeComparator()); System.out.println(personList);
在上述代碼中,我們實(shí)現(xiàn)了一個(gè)PersonAgeComparator
比較器,按照年齡大小進(jìn)行比較。在調(diào)用Collections.sort()
方法時(shí),傳入該比較器作為參數(shù),即可按照指定的規(guī)則進(jìn)行排序。
運(yùn)行上述代碼,結(jié)果如下所示:
[Person{name='李四', age=18}, Person{name='張三', age=20}, Person{name='王五', age=21}]
除此之外,我們還可以使用lambda表達(dá)式來(lái)簡(jiǎn)化比較器的實(shí)現(xiàn):
Collections.sort(personList, (o1, o2) -> o1.getAge() - o2.getAge());
3、Comparable和Comparator的區(qū)別
Comparable是內(nèi)部比較器,而Comparator是外部比較器。實(shí)現(xiàn)Comparable的類(lèi),在其內(nèi)部定義了比較規(guī)則;而使用Comparator時(shí),則需要單獨(dú)定義一個(gè)外部比較器。
Comparable的排序規(guī)則是固定的,不可更改;而Comparator的排序規(guī)則是可以根據(jù)需要自己定義的。
Comparable的排序規(guī)則只適用于該類(lèi)的對(duì)象,而Comparator的排序規(guī)則可以適用于不同類(lèi)型的對(duì)象。
當(dāng)我們需要對(duì)自定義類(lèi)型進(jìn)行排序時(shí),如果實(shí)現(xiàn)了Comparable接口,就意味著該類(lèi)型具有了默認(rèn)的排序規(guī)則;如果沒(méi)有實(shí)現(xiàn)Comparable接口,則需要單獨(dú)定義Comparator。
總的來(lái)說(shuō),Comparable和Comparator都是Java中用于集合排序的接口,但它們有各自的優(yōu)缺點(diǎn)。在實(shí)際編程中,我們需要根據(jù)具體情況選擇使用哪種方式,才能更加高效地完成任務(wù)。
以上就是一文搞清楚Java中Comparable和Comparator的區(qū)別的詳細(xì)內(nèi)容,更多關(guān)于Java Comparable和Comparator區(qū)別的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
深入探究MyBatis插件機(jī)制靈活擴(kuò)展及自定義增強(qiáng)框架能力
這篇文章主要介紹了深入探究MyBatis插件機(jī)制靈活擴(kuò)展及自定義增強(qiáng)框架能力2024-01-01java使用hadoop實(shí)現(xiàn)關(guān)聯(lián)商品統(tǒng)計(jì)
本篇文章java使用hadoop實(shí)現(xiàn)關(guān)聯(lián)商品統(tǒng)計(jì),可以實(shí)現(xiàn)商品的關(guān)聯(lián)統(tǒng)計(jì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2016-10-10IDEA 中使用 ECJ 編譯出現(xiàn) java.lang.IllegalArgumentException的錯(cuò)誤問(wèn)題
這篇文章主要介紹了IDEA 中使用 ECJ 編譯出現(xiàn) java.lang.IllegalArgumentException問(wèn)題 ,本文內(nèi)容簡(jiǎn)短給大家介紹的好,需要的朋友可以參考下2020-05-05Spring Boot實(shí)現(xiàn)郵件發(fā)送必會(huì)的5種姿勢(shì)
這篇文章主要給大家介紹了關(guān)于Spring Boot實(shí)現(xiàn)郵件發(fā)送必會(huì)的5種姿勢(shì),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07Java5種遍歷HashMap數(shù)據(jù)的寫(xiě)法
這篇文章主要介紹了Java5種遍歷HashMap數(shù)據(jù)的寫(xiě)法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03