首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 入門教學 (17):Comparable 與 Comparator 介面完整攻略

     編輯:Java 相關知識

為什麼排序需要介面?

陣列或集合裡的物件 (如 Course) 沒有天生的大小關係。Arrays.sort() 需要一個「比較契約」:任意兩個物件 a、b,能判斷 a<b、a=b、a>b。Java 用介面定義這個契約:

  • Comparable<T>:物件自己知道怎麼跟別人比 (自然排序)。
  • Comparator<T>:外部裁判決定怎麼比 (客製排序)。

情境:課程陣列依價格排序

public class Course {
    private String title;
    private double price;
    // 建構子、getter/setter 略
}

方法一:實作 Comparable (唯一預設排序)

public class Course implements Comparable<Course> {
    // ... 原有欄位 ...
    @Override
    public int compareTo(Course other) {
        if (other == null) return 1;
        return Double.compare(this.price, other.price); // 價格升序
    }
}

// 使用
Course[] courses = { new Course("Java", 2000), new Course("Python", 1500) };
Arrays.sort(courses); // 直接排序,不傳比較器
// 結果:Python(1500), Java(2000)

⚠️ 限制:一個類別只能有一種自然排序。若明天要按標題字母序排,compareTo 無法同時滿足。

方法二:使用 Comparator (多種排序任意切換)

import java.util.Comparator;

public class PriceComparator implements Comparator<Course> {
    @Override
    public int compare(Course c1, Course c2) {
        if (c1 == c2) return 0;
        if (c1 == null) return -1;
        if (c2 == null) return 1;
        return Double.compare(c1.getPrice(), c2.getPrice());
    }
}

// 使用
Arrays.sort(courses, new PriceComparator()); // 傳入比較器

// 同一組資料,換個比較器即可按標題排
Arrays.sort(courses, Comparator.comparing(Course::getTitle));

Comparator 進階用法 (Java 8+)

List list = Arrays.asList(courses);

// 價格降序
list.sort(Comparator.comparingDouble(Course::getPrice).reversed());

// 價格升序 -> 標題降序
list.sort(Comparator
    .comparingDouble(Course::getPrice)
    .thenComparing(Comparator.comparing(Course::getTitle).reversed()));

// null 安全:沒價格的排最後
list.sort(Comparator.nullsLast(Comparator.comparingDouble(Course::getPrice)));

常見新手錯誤與修正

錯誤寫法問題修正
return this.price - other.price;double 相減可能溢位/精度遺失Double.compare(this.price, other.price)
return (int)(this.price - other.price);強制轉型截斷,大數字會判斷錯誤同上
忘記處理 null拋 NullPointerException先判斷 if (o == null) return 1; 或用 nullsLast
compareTo 與 equals 不一致TreeSet 會把不相等物件視為重複主鍵相等時 compareTo 必須回 0

實戰小練習

  1. 建立 Student(name, score) 類別,實作 Comparable 依分數降序。
  2. 寫一個 NameComparator 依姓名筆畫數排序 (提示:Collator.getInstance(Locale.TRADITIONAL_CHINESE))。
  3. 對同一組學生陣列,分別用自然排序與 NameComparator 排序並印出。

總結

  • Comparable = 內建預設排序,implements Comparable<T> + compareTo。
  • Comparator = 外部可換裝排序,implements Comparator<T> + compare,或用 Lambda。
  • 記得用 Double.compare/Integer.compare 避免溢位。
  • 善用 Comparator.comparing/thenComparing/reversed/nullsLast 鏈式 API,程式碼最乾淨。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved