5 分鐘搞定 Java Comparable 接口

2021-02-19 動力節點Java學院
Comparable接口時用來幹什麼的呢?

我們應該如何對事物進行比較和排序?這問題聽上去有點莫名其妙,但我希望你認真考慮一下。比方說,我們有一組蘋果:

例1

我們要怎樣對它們進行排序呢?我們希望通過重量進行排序嗎?如果是的話,排序是從最輕到最重還是從最重到最輕?當我們對它們進行排序的時候,我們需要反覆比較兩個蘋果的重量,直到正確地排好所有的蘋果。蘋果1比蘋果2重?那它比蘋果3重嗎?我們需要不斷比較,直到完成排序。Comparable接口可以幫助我們實現這一目標。Comparable本身不能對對象進行排序,但接口定義的方法 int compareTo(T)可以。

compareTo(T)如何工作

讓我們通過使用compareTo()方法來看看哪個蘋果更重,開始吧。

例2

compareTo()方法的工作原理是返回一個int值——或正,或負,或為零。它通過調用作為參數的對象來比較對象。負數表示調用的對象比參數「輕」。如果我們用大小來比較蘋果,那麼上面的調用會返回一個負數,例如-400,因為紅蘋果比青蘋果小。如果兩個蘋果重量相等,那麼調用將返回0。如果紅蘋果更重,那麼compareTo()將返回一個正數,例如68。

compareTo()的靈活性

如果我們反覆調用上面的compareTo()方法,那麼我們可以通過大小來排序,這很棒,但並非故事的結束。如果我們想通過顏色來給蘋果排序呢?抑或是重量?我們也可以做到。關鍵是,我們的客戶——讓我們叫他胖子農夫(見例3),需要在我們開始開發之前精確定義需要如何對蘋果進行排序。

例3

他可以通過回答這兩個問題來做到這一點:

他希望蘋果如何進行排序?他希望我們比較什麼特徵?

在那樣的環境中,「小於」,「等於」和「大於」指的是什麼意思?

也可以使用多個特徵,這個後面我們會講。

例1:通過重量排序蘋果

在第一個例子中,我們將通過重量對蘋果排序。只需要一行代碼。

Collections.sort(apples);

例4

上面的代碼行可以為我們做到所有的排序工作,只要我們事先定義好如何對蘋果進行排序(這就需要多行代碼了)。

讓我們開始寫蘋果類吧。

public class Apple implements Comparable { private String variety; private Color color; private int weight; @Override public int compareTo(Apple other) { if (this.weight < other.weight) { return -1; } if (this.weight == other.weight) { return 0; } return 1; }}

例5

這是Apple類的第一個版本。由於我們使用的是compareTo方法,並且正在排序蘋果,所以我實現了Comparable接口。在這第一個版本中,我們通過重量比較對象。在我們的compareTo()方法中,我們寫一個if條件,說明如果這個蘋果的重量小於其他的蘋果,那麼返回一個負數,為了保持簡單,我們假定它為-1。請記住,這意味著這個蘋果輕於Apple 『other』。在第二個if語句中,我們要說明,如果蘋果重量相等,那麼返回一個0。當然,如果這個蘋果既不是更輕,又不是一樣重,那就只能比其他蘋果更重了。在這種情況下,我們返回一個正數,假定為1。

例2:通過多個特徵排序蘋果

正如我前面提到的,我們還可以使用compareTo()比較多個特徵。比方說,我們第一通過品種排序蘋果,但如果兩個蘋果是同一品種,那麼我們就按顏色排序。最後,如果這兩個特性相同,那麼我們將按重量排序。雖然我們可以手動實現這件事,就像我在最後一個例子中做的那樣,但是其實可以用一種簡潔得多的方式實現。一般來說,最好是重用現有的代碼,而不是自己寫。我們可以在Integer、String和枚舉類中使用compareTo方法來比較值。由於我們沒有使用Integer對象,用了int,所以我們不得不使用來自於Integer包裝器類的一個靜態的helper方法來比較兩個值。

public class Apple implements Comparable { private String variety; private Color color; private int weight; @Override public int compareTo(Apple other) { int result = this.variety.compareTo(other.variety); if (result != 0) { return result; } if (result == 0) { result = this.color.compareTo(other.color); } if (result != 0) { return result; } if (result == 0) { result = Integer.compare(this.weight, other.weight); } return result; }}

例6

在例6中,我們比較了客戶指定的蘋果的第一特性,它們的品種。如果compareTo()調用的結果為非零,那麼我們返回值。否則,我們調用另一個compareTo()直到得到一個非零值,或者直到已經比較完這三個特徵。儘管此代碼可以工作,但它不是最有效或乾淨的解決方案。在例3中,我們重構我們的代碼,使其更簡單。

@Overridepublic int compareTo(Apple other) { int result = this.variety.compareTo(other.variety); if (result == 0) { result = this.color.compareTo(other.color); } if (result == 0) { result = Integer.compare(this.weight, other.weight); } return result;}

例7

正如你所看到的,這大大減少了代碼,並且每一次比較只要一行代碼。如果一個compareTo()調用的結果是零,那麼我們就轉移到下一個相同if語句的比較中。順便說一句,這是成為Clean Coder的一個很好的例子。通常情況下,你不需要立即寫出乾淨的代碼;你可以從一個粗略的想法開始,使其可以工作,然後不斷改進,直到你儘可能得讓它乾淨就可以了。

Comparable,hashCode以及Equals

你可能會注意到compareTo()看起來有點像hashCode()和equals()方法。但是,它們有一個重要的區別。對於hashCode()和equals()方法,比較個體屬性的順序不影響返回的值,但是,在compareTo()中,通過你比較對象的順序來定義對象的順序。

結論

在結論中我只想強調Comparable接口是多麼的重要。它既用於java.util.Arrays,也用於java.util.Collections實用程序類,來排序元素和搜索排序集合中的元素。使用TreeSet和Tree Map,就更簡單了——想要它們會自動排序必須實現Comparable接口的元素。

相關焦點

  • 【編程基礎】java Comparable接口如何使用
    CompareTo函數是Comparable接口的一個方法,Comparable接口源碼如下:public interface Comparable<T> { /** * Compares this object to the specified object to determine their relative
  • 花了 5 分鐘就搞定了 Java 下載和解析 Excel
    工欲善其事必先利其器,果然有道理,之前經常做一些 Excel 的解析和寫入,大家估計也對 jxl 和 poi 有所耳聞,操作起來那是一塌糊塗,需要了解裡面的各種變量,然而這次我們使用的是阿里開源的 EasyExcel,5分鐘搞定下載和上傳解析。
  • Integer 為什麼要實現 Comparable 接口?
    一、為什麼需要實現這個接口呢?: interfacedemo.Person cannot be cast to java.lang.Comparable at java.util.ComparableTimSort.countRunAndMakeAscending(Unknown Source) at java.util.ComparableTimSort.sort(Unknown Source) at
  • 【第11章:Java常用類庫】_比較器(Comparable、Comparator)
    Hellodelightful      27      88.2snowDrink       18      90.1xy      18      92.2kasumi 24      96.5ayani   23      98.5hayabusa        28      98.5Comparable
  • 可能是把 Java 接口講得最通俗的一篇文章
    http://www.itwanger.com/java/2019/11/14/java-serializable.html3)不要在定義接口的時候使用 final 關鍵字,否則會報編譯錯誤,因為接口就是為了讓子類實現的,而 final 阻止了這種行為。
  • 我們常用的 Integer 內部為什麼會去實現 Comparable 接口?
    一、為什麼需要實現這個接口呢?: interfacedemo.Person cannot be cast to java.lang.Comparable at java.util.ComparableTimSort.countRunAndMakeAscending(Unknown Source) at java.util.ComparableTimSort.sort(Unknown Source) at
  • Java 本地接口 JNI 使用詳解
    也可直接搜索公眾號緯庫軟體或waycool001進行關注,查看歷史消息即可。如果你覺得文章不錯,也可點擊右上角的「...」分享到朋友圈,大家需要正能量。對於java程式設計師來說,java語言的好處和優點,我想不用我說了,大家自然會說出很多一套套的。但雖然我們作為java程式設計師,但我們不得不承認java語言也有一些它本身的缺點。比如在性能、和底層打交道方面都有它的缺點。所以j
  • 好奇,我們常用的 Integer 內部為什麼會去實現 Comparable 接口,他的作用是什麼?
    今天在開發中無意看到Integer包裝類內部實現了Comparable接口,因此探查一下該接口作用:查看API解釋:此接口強行對實現它的每個類的對象進行整體排序。這種排序被稱為類的自然排序,類的 compareTo 方法被稱為它的自然比較方法。一、為什麼需要實現這個接口呢?
  • java集合面試攻略
    java集合架構圖,來源於網絡java集合的2個頂級接口Collection和Map。話不多說,接下來我們對它們作一一介紹。先對java.util.Map的4個常用實現類做簡單的介紹及對比。比較古老,從JDK1.0就開始有了。線程安全,操作時鎖整個表,效率低,現在基本被遺棄。
  • java調用webservice接口的幾種方法
    webservice的 發布一般都是使用WSDL(web service descriptive language)文件的樣式來發布的,在WSDL文件裡面,包含這個webservice暴露在外面可供使用的接口。
  • 談談Java接口Result設計
    因為這個問題本身沒有講清楚「對什麼東西的處理」要用Result還是異常的方式,即這裡沒有講清楚我們要解決的問題是什麼。事實上我們常說的「失敗」,往往混淆了2種含義:系統異常:比如網絡超時、DB異常、緩存超時等,調用方一般不太可能基於這些錯誤類型做不同的業務邏輯,常用用於日誌和監控,方便定位排查。
  • Java springMVC] Restful風格API接口設計
    在Restful風格中,用戶請求的url使用同一個url而用請求方式:get,post,delete,put...等方式對請求的處理方法進行區分,這樣可以在前後臺分離式的開發中使得前端開發人員不會對請求的資源地址產生混淆和大量的檢查方法名的麻煩,形成一個統一的接口。
  • 學透Excel函數,5分鐘搞定1天工作量
    輸入計算公式,3秒搞定!慄子2:統計業績時,如何讓1-4季度的總業績自動計算到匯總表?所以,如果你會使用Excel進行跨表匯總,一次搞定,多輕鬆?如果不懂Excel,就會陷入盲目的手動操作,不及時交差,挨批可能是分分鐘的事,想到無止境的加班更難受。相反,如果你學會一個Excel技巧,你就可以多一次和家人吃飯的時間,多一次和朋友看電影的時間,多一次玩遊戲放鬆自己的時間。
  • Java語言的5個特點,幫助新手了解Java
    Java語言的語法與C語言和C++語言很接近,使得大多數程式設計師很容易學習和使用Java。Java語言提供類、接口和繼承等原語,為了簡單起見,只支持類之間的單繼承,但支持接口之間的多繼承,並支持類與接口之間的實現機制(關鍵字為 implements)。
  • 幹了5年Java,我終於玩會了IDEA!
    Grep Console在控制臺支持篩選,類似Shell命令的cat 1.txt | grep '11',這個還是很有用的Lombok plugin這個不解釋,使用lombok必須要裝的一個插件CodeGlance代碼編輯區迷你縮放圖插件,非常好用
  • Java接口自動化之log4j日誌框架
    上一篇Java
  • 【PPT技巧】100頁的Word轉PPT,只要5分鐘就搞定
    5分鐘就能搞定!Word轉成PPT是最常見的一種操作,藉助Word自帶的功能就能搞定。相比前者,PPT轉Word其實更簡單,只需兩步就能搞定。1) 打開PPT文檔;2) 點擊「文件」→「另存為」,在右窗格設置好文件名及路徑後,將文檔類型修改為「大綱/RTF文件(*.rtf)」 ;直接將PPT保存為「RTF文件」就可以了好了,直接雙擊這個文件吧。看!最快PPT轉Word技巧不是吹的吧。
  • 每個Java程式設計師需要了解的8個Java開發工具
    官方網站: http://sparkjava.com/ 2. jClarityjClarity是兩款產品的結合:illuminate用於性能監控,而census則可以收集日誌和分析數據。jClarity支持雲集成,並且其框架緊湊輕巧。
  • Java伺服器接口快速開發之Servlet詳細教程
    →[設為星標⭐]開發工具和環境由於我們的接口開發語言是 java,那麼當然還是以 eclipse 為主。這裡我使用的是帶有 web 插件的 eclipse。我們俗稱 javaEE。做伺服器開發的同學當然知道資料庫也是必不可少的,咱不能做一個沒有真實數據的接口。資料庫用的 mysql。 這些工具網上都是可以百度進行下載的。這裡不贅述了。資料庫創建以及java中jdbc驅動加載資料庫不熟悉資料庫的小夥伴可以下載一個可視化的資料庫操作界面。
  • 《Java 開發接口》+《小程序入門》
    這是 4 月 5 日發在我的朋友圈裡,標題:我要學習,學習使我快樂[捂臉][捂臉]。PS:《Java 開發接口》比我想像中寫的慢,業餘時間基本投進去了,晚上要等我兒子睡了,9 點後才能做自己的事。最近學習任務比較重,想在星球二期進行三個固定專題分享:小程序入門,Java 開發接口,Android 自定義 View,計劃在二期(5 月 7 號)來臨,完成 Java 部分,但我高估了自己,這份教程起稿於清明節前後,我以為能像《Python 3 極簡教程》一樣,在一個國慶節搞定,現實困難重重,解決一個,又來一個,沒人能幫我,只能谷歌,很容易陷於死胡同,小白還在爬坑中,都想放棄,但我又屬於既然開始了