java中元素排序Comparable和Comparator的區(qū)別
初次碰到這個問題是之前有一次電話面試,問了一個小時的問題,其中有一個問題就問到Comparable和Comparator的區(qū)別,當(dāng)時沒答出 來。之后是公司入職時候做的一套Java編程題,里面用JUnit跑用例的時候也用到了Comparator接口,再加上JDK的大量的類包括常見的 String、Byte、Char、Date等都實現(xiàn)了Comparable接口,因此要學(xué)習(xí)一下這兩個類的區(qū)別以及用法。
Comparable
Comparable可以認(rèn)為是一個內(nèi)比較器,實現(xiàn)了Comparable接口的類有一個特點,就是這些類是可以和自己比較的,至于具體和另一個實現(xiàn)了Comparable接口的類如何比較,則依賴compareTo方法的實現(xiàn),compareTo方法也被稱為自然比較方法。如果開發(fā)者add進入一個Collection的對象想要Collections的sort方法幫你自動進行排序的話,那么這個對象必須實現(xiàn)Comparable接口。compareTo方法的返回值是int,有三種情況:
1、比較者大于被比較者(也就是compareTo方法里面的對象),那么返回正整數(shù)
2、比較者等于被比較者,那么返回0
3、比較者小于被比較者,那么返回負(fù)整數(shù)
寫個很簡單的例子:
public class Domain implements Comparable<Domain> { private String str; public Domain(String str) { this.str = str; } public int compareTo(Domain domain) { if (this.str.compareTo(domain.str) > 0) return 1; else if (this.str.compareTo(domain.str) == 0) return 0; else return -1; } public String getStr() { return str; } } public static void main(String[] args) { Domain d1 = new Domain("c"); Domain d2 = new Domain("c"); Domain d3 = new Domain("b"); Domain d4 = new Domain("d"); System.out.println(d1.compareTo(d2)); System.out.println(d1.compareTo(d3)); System.out.println(d1.compareTo(d4)); }
運行結(jié)果為:
0
1
-1
注意一下,前面說實現(xiàn)Comparable接口的類是可以支持和自己比較的,但是其實代碼里面Comparable的泛型未必就一定要是Domain,將泛型指定為String或者指定為其他任何任何類型都可以----只要開發(fā)者指定了具體的比較算法就行。?
Comparator
Comparator可以認(rèn)為是是一個外比較器,個人認(rèn)為有兩種情況可以使用實現(xiàn)Comparator接口的方式:
1、一個對象不支持自己和自己比較(沒有實現(xiàn)Comparable接口),但是又想對兩個對象進行比較
2、一個對象實現(xiàn)了Comparable接口,但是開發(fā)者認(rèn)為compareTo方法中的比較方式并不是自己想要的那種比較方式
Comparator接口里面有一個compare方法,方法有兩個參數(shù)T o1和T o2,是泛型的表示方式,分別表示待比較的兩個對象,方法返回值和Comparable接口一樣是int,有三種情況:
1、o1大于o2,返回正整數(shù)
2、o1等于o2,返回0
3、o1小于o3,返回負(fù)整數(shù)
寫個很簡單的例子,上面代碼的Domain不變(假設(shè)這就是第2種場景,我對這個compareTo算法實現(xiàn)不滿意,要自己寫實現(xiàn)):
public class DomainComparator implements Comparator<Domain> { public int compare(Domain domain1, Domain domain2) { if (domain1.getStr().compareTo(domain2.getStr()) > 0) return 1; else if (domain1.getStr().compareTo(domain2.getStr()) == 0) return 0; else return -1; } }
public static void main(String[] args) { Domain d1 = new Domain("c"); Domain d2 = new Domain("c"); Domain d3 = new Domain("b"); Domain d4 = new Domain("d"); DomainComparator dc = new DomainComparator(); System.out.println(dc.compare(d1, d2)); System.out.println(dc.compare(d1, d3)); System.out.println(dc.compare(d1, d4)); }
看一下運行結(jié)果:
0
1
-1
當(dāng)然因為泛型指定死了,所以實現(xiàn)Comparator接口的實現(xiàn)類只能是兩個相同的對象(不能一個Domain、一個String)進行比較了,因此實現(xiàn)Comparator接口的實現(xiàn)類一般都會以"待比較的實體類+Comparator"來命名
總結(jié)
總結(jié)一下,兩種比較器Comparable和Comparator,后者相比前者有如下優(yōu)點:
1、如果實現(xiàn)類沒有實現(xiàn)Comparable接口,又想對兩個類進行比較(或者實現(xiàn)類實現(xiàn)了Comparable接口,但是對compareTo方法內(nèi)的比較算法不滿意),那么可以實現(xiàn)Comparator接口,自定義一個比較器,寫比較算法
2、實現(xiàn)Comparable接口的方式比實現(xiàn)Comparator接口的耦合性 要強一些,如果要修改比較算法,要修改Comparable接口的實現(xiàn)類,而實現(xiàn)Comparator的類是在外部進行比較的,不需要對實現(xiàn)類有任何修 改。從這個角度說,其實有些不太好,尤其在我們將實現(xiàn)類的.class文件打成一個.jar文件提供給開發(fā)者使用的時候。實際上實現(xiàn)Comparator 接口的方式后面會寫到就是一種典型的策略模式。
當(dāng)然,這不是鼓勵用Comparator,意思是開發(fā)者還是要在具體場景下選擇最合適的那種比較器而已。
到此這篇關(guān)于java中元素排序Comparable和Comparator的區(qū)別的文章就介紹到這了,更多相關(guān)java Comparable和Comparator內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot+thymeleaf+ajax實現(xiàn)局部刷新詳情
這篇文章主要介紹了SpringBoot+thymeleaf+ajax實現(xiàn)局部刷新詳情,文章圍繞主題展開詳細(xì)的內(nèi)容介紹具有一定的參考價值,需要的小伙伴可以參考一下2022-09-09springboot后端配置多個數(shù)據(jù)源、Mysql數(shù)據(jù)庫的便捷方法
實現(xiàn)springboot 后端配置多個數(shù)據(jù)源、Mysql數(shù)據(jù)庫,只需要新建 Mapper、實體類 相應(yīng)的文件夾,將不同數(shù)據(jù)源的文件保存到對應(yīng)的文件夾下,添加綁定數(shù)據(jù)庫配置Config,就可以輕松完成2021-08-08Spring Boot中的WebSocketMessageBrokerConfigurer接口使用
在SpringBoot中,我們可以使用 WebSocketMessageBrokerConfigurer接口來配置WebSocket消息代理,以實現(xiàn)實時通信,具有一定的參考價值,感興趣的可以了解一下2023-11-11mybatis多層嵌套resultMap及返回自定義參數(shù)詳解
這篇文章主要介紹了mybatis多層嵌套resultMap及返回自定義參數(shù)詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12詳解Springboot之整合JDBCTemplate配置多數(shù)據(jù)源
這篇文章主要介紹了詳解Springboot之整合JDBCTemplate配置多數(shù)據(jù)源,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java的小伙伴們有很好的幫助,需要的朋友可以參考下2021-04-04Java C++題解leetcode 1684統(tǒng)計一致字符串的數(shù)目示例
這篇文章主要為大家介紹了Java C++題解leetcode 1684統(tǒng)計一致字符串的數(shù)目示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-01-01Java?SimpleDateFormat與System類使用示例詳解
這篇文章主要介紹了Java?SimpleDateFormat與System類使用示例,對于SimpleDateFormat類,是一個用來區(qū)分區(qū)域設(shè)置的方式進行日期的是指,以及對日期進行處理分析的一個實現(xiàn)類2022-11-11