Effective Java Item14 考慮實作 Comparable
整理 Effective Java 書中 Item 14: Consider implementing Comparable 心得筆記
主旨
如果你的類別有「自然順序」(例如時間、數字、字母順序),實作 Comparable
介面將大大提升它的實用性。這麼做可以讓物件支援排序、搜尋、去重,並輕鬆整合進 TreeSet、TreeMap、Arrays.sort 等 API 中,幾乎所有 Java 的值物件(例如 String、BigDecimal、Enum)都有實作 Comparable。
基本觀念:Comparable 是什麼?
Comparable
是一個泛型介面,裡面只有一個方法:
你實作這個方法後,Java 就知道怎麼幫你的物件做排序了。排序邏輯依照回傳值定義:
- 回傳負數:代表 this 小於 o
- 回傳 0:代表兩者相等
- 回傳正數:代表 this 大於 o
例如:
怎麼使用 compareTo 實作排序?
你可以從最重要的欄位開始比對,如果相同,再比下一個欄位。這種寫法類似排序規則的「第一優先、第二優先、第三優先」。
如果想更簡潔,Java 8 提供了 Comparator
的建構方法,可以把這些邏輯串起來:
這種寫法雖然執行稍慢(約慢 10%),但可讀性更高,也比較不容易出錯。
注意事項:compareTo 合約與 equals 的一致性
compareTo
要符合 對稱性、傳遞性、一致性(跟 equals 很像)- 最好讓
compareTo(a, b) == 0
時,也要讓a.equals(b) == true
- 否則像
TreeSet
這種集合可能只看 compareTo,不看 equals,會導致行為不一致
舉例來說:
用 HashSet
會存兩個元素,但用 TreeSet
只會存一個。
如果真的無法保證一致性,請在類別說明中明確註記:
注意:本類別的自然排序與 equals 不一致。
真實世界範例
假設你有個訂單系統,Order
類別根據下單時間排序,只要這樣實作:
之後就能直接用 Collections.sort()
排序,也能用 TreeSet<Order>
來做自動排序+去重,大幅減少自訂 comparator 或排序邏輯的需求。
小結
實作 Comparable
是 Java 類別的重要升級,能讓你善用排序與泛型集合的功能,簡化邏輯與提升整合性。寫 compareTo()
時請使用 compare()
系列方法取代 <
與 >
,避免錯誤與溢位問題。如果類別有明確的排序規則,不要猶豫,實作 Comparable
就對了!