Java Academy · Pelajaran

Antara Muka Comparable

Laksanakan Comparable untuk memberikan kelas susunan semula jadi dan gunakannya dengan Collections.sort.

Pelajaran 1 daripada 413 langkah

Antara Muka Comparable ialah pelajaran Java Academy percuma di CoddyKit. Ini ialah pelajaran 1 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Java Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Java Academy merangkumi sejumlah 4 pelajaran.

Antara Muka Comparable

Comparable<T> memberikan sesebuah class susunan semula jadi. Laksanakan antara muka ini supaya tika class boleh diisih dengan Collections.sort(), Arrays.sort() dan koleksi terisih seperti TreeSet.

Melaksanakan Comparable

Laksanakan compareTo(T other) supaya mengembalikan nilai negatif (this < other), sifar (sama) atau positif (this > other).

class Product implements Comparable<Product> {
    private final String name;
    private final double price;

    Product(String name, double price) {
        this.name = name; this.price = price;
    }

    @Override
    public int compareTo(Product other) {
        return Double.compare(this.price, other.price); // ascending by price
    }

    @Override public String toString() { return name + "($" + price + ")"; }
}

List<Product> products = new ArrayList<>(List.of(
    new Product("Mouse", 29.99),
    new Product("Laptop", 999.0),
    new Product("Keyboard", 79.99)
));
Collections.sort(products);
System.out.println(products); // [Mouse($29.99), Keyboard($79.99), Laptop($999.0)]

Kontrak compareTo

Pelaksanaan Comparable yang betul memerlukan pematuhan terhadap kontrak:

  • Antisimetri: sgn(a.compareTo(b)) == -sgn(b.compareTo(a))
  • Transitiviti: jika a > b dan b > c, maka a > c
  • Ketekalan: a.compareTo(b) == 0 bermaksud a.equals(b); pematuhan ini sangat disyorkan

Membandingkan Primitif dengan Selamat

Jangan sekali-kali menolak nilai primitif dalam compareTo — limpahan integer boleh menghasilkan keputusan yang salah. Gunakan Integer.compare(), Double.compare() dan sebagainya.

// WRONG: integer subtraction can overflow
int compareTo(Player other) {
    return this.score - other.score; // overflow if scores differ by > Integer.MAX_VALUE
}

// CORRECT: use Integer.compare
int compareTo(Player other) {
    return Integer.compare(this.score, other.score);
}

// For strings: delegate to String.compareTo
int compareTo(Player other) {
    return this.name.compareTo(other.name); // String handles it correctly
}

Susunan Semula Jadi dalam TreeSet

Class yang melaksanakan Comparable ditempatkan secara automatik dalam koleksi terisih seperti TreeSet dan TreeMap.

class Priority implements Comparable<Priority> {
    enum Level { LOW, MEDIUM, HIGH, CRITICAL }
    final Level level;
    final String task;
    Priority(Level level, String task) { this.level = level; this.task = task; }
    @Override
    public int compareTo(Priority other) {
        return this.level.compareTo(other.level); // enum ordinal order
    }
    @Override public String toString() { return level + ": " + task; }
}

TreeSet<Priority> queue = new TreeSet<>();
queue.add(new Priority(Priority.Level.CRITICAL, "Fix prod crash"));
queue.add(new Priority(Priority.Level.LOW, "Update docs"));
queue.add(new Priority(Priority.Level.HIGH, "Deploy feature"));
queue.forEach(System.out::println);
// LOW: Update docs
// HIGH: Deploy feature
// CRITICAL: Fix prod crash

Comparable Berbilang Medan

Untuk mengisih berdasarkan berbilang medan, rangkaikan perbandingan: medan utama, kemudian medan sekunder jika medan utama sama.

class Employee implements Comparable<Employee> {
    final String dept, name;
    final double salary;

    Employee(String dept, String name, double salary) {
        this.dept = dept; this.name = name; this.salary = salary;
    }

    @Override
    public int compareTo(Employee other) {
        int deptCmp = this.dept.compareTo(other.dept);
        if (deptCmp != 0) return deptCmp;           // primary: by dept
        return this.name.compareTo(other.name);      // secondary: by name
    }
}

Ketekalan Comparable dan equals

Sangat disyorkan (tetapi tidak diwajibkan) agar a.compareTo(b) == 0 jika dan hanya jika a.equals(b). Pelanggaran ini menyebabkan pepijat yang sukar dikesan dalam set dan peta terisih.

// BigDecimal violates this: new BigDecimal("2.0").compareTo(new BigDecimal("2.00")) == 0
// but new BigDecimal("2.0").equals(new BigDecimal("2.00")) == false

// This causes TreeSet to treat them as equal (only one stored)
TreeSet<java.math.BigDecimal> set = new TreeSet<>();
set.add(new java.math.BigDecimal("2.0"));
set.add(new java.math.BigDecimal("2.00"));
System.out.println(set.size()); // 1 — compareTo-equal → same element

Pengisihan dengan Collections.sort

Collections.sort() dan Arrays.sort() menggunakan susunan semula jadi yang ditakrifkan oleh Comparable.

List<String> names = new ArrayList<>(List.of("Charlie", "Alice", "Bob"));
Collections.sort(names); // natural alphabetical order
System.out.println(names); // [Alice, Bob, Charlie]

String[] arr = {"banana", "apple", "cherry"};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr)); // [apple, banana, cherry]

// Stream sorted() uses natural order
names.stream().sorted().forEach(System.out::println);

Comparable dalam Carian Binari

Collections.binarySearch() memerlukan senarai diisih mengikut susunan semula jadi dan elemennya melaksanakan Comparable.

List<Integer> sorted = new ArrayList<>(List.of(1, 3, 5, 7, 9, 11));
int idx = Collections.binarySearch(sorted, 7);
System.out.println("Found 7 at index: " + idx); // 3

int missing = Collections.binarySearch(sorted, 4);
System.out.println("4 not found, insertion point: " + (-missing - 1)); // 2

Comparable berbanding Comparator

Perbezaan utama:

  • Comparable: mentakrifkan susunan semula jadi class itu sendiri — satu bagi setiap class
  • Comparator: mentakrifkan susunan luaran — tidak terhad dan boleh digabungkan

Amali: Papan Pendahulu

Papan pendahulu yang menggunakan Comparable untuk susunan semula jadi berdasarkan skor menurun.

class LeaderboardEntry implements Comparable<LeaderboardEntry> {
    final String player;
    final int score;
    final long timestamp;

    LeaderboardEntry(String player, int score) {
        this.player = player; this.score = score;
        this.timestamp = System.nanoTime();
    }

    @Override
    public int compareTo(LeaderboardEntry other) {
        int scoreCmp = Integer.compare(other.score, this.score); // descending
        if (scoreCmp != 0) return scoreCmp;
        return Long.compare(this.timestamp, other.timestamp); // earlier = higher
    }

    @Override public String toString() { return player + ": " + score; }
}

TreeSet<LeaderboardEntry> board = new TreeSet<>();
board.add(new LeaderboardEntry("Alice", 950));
board.add(new LeaderboardEntry("Bob", 1200));
board.add(new LeaderboardEntry("Carol", 950));
board.forEach(System.out::println);
// Bob: 1200 / Alice: 950 / Carol: 950

Semakan Pantas

Apakah nilai yang dikembalikan oleh compareTo() apabila objek semasa lebih kecil daripada argumen?

Imbas Kembali: Antara Muka Comparable

Perkara penting:

  • Laksanakan Comparable untuk mentakrifkan susunan semula jadi sesebuah class
  • compareTo mengembalikan nilai negatif (lebih kecil), sifar (sama) atau positif (lebih besar)
  • Gunakan Integer.compare()/Double.compare() — jangan sekali-kali melakukan penolakan kerana risiko limpahan
  • Rangkaikan perbandingan untuk pengisihan berbilang medan: utama → sekunder
  • Susunan semula jadi digunakan oleh Collections.sort, Arrays.sort, TreeSet dan TreeMap
  • Comparable mentakrifkan SATU susunan; gunakan Comparator untuk berbilang susunan
Percuma untuk bermula

Pelajari Java dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
104
Pelajaran
374

Soalan Lazim

Adakah pelajaran “Antara Muka Comparable” percuma?

Ya — teks penuh “Antara Muka Comparable” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Java Academy, tingkat taraf kepada CoddyKit PRO. Kursus Java Academy merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Antara Muka Comparable”?

Laksanakan Comparable untuk memberikan kelas susunan semula jadi dan gunakannya dengan Collections.sort. Anda berlatih Java Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Java Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Java Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 1 daripada 4.

Berapa lamakah pelajaran “Antara Muka Comparable” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Java Academy ini?

Ya. Setiap pelajaran Java Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Antara Muka Comparable
  2. Comparator dan Pengisihan Lambda
  3. Pengisihan Berbilang Kunci dengan thenComparing
  4. Pengisihan Tatasusunan dan Koleksi dalam Amalan
← Kembali ke Java Academy