Menu
CoddyTech

compareTo() và Comparable

Thuộc phần Lập trình hướng đối tượng trong hành trình Java của Coddy. Bài học 44 trên 87.

Giao diện Comparable cho phép các đối tượng xác định thứ tự tự nhiên. Khi triển khai giao diện này, lớp có thể tự động được sắp xếp bằng các phương thức như Collections.sort() hoặc được lưu trong các bộ sưu tập đã sắp xếp như TreeSet.

Giao diện yêu cầu bạn triển khai một phương thức duy nhất: compareTo(). Phương thức này so sánh đối tượng hiện tại với một đối tượng khác và trả về một số nguyên cho biết thứ tự tương đối của chúng:

  • Giá trị âm: đối tượng này đứng trước đối tượng kia
  • Số không: hai đối tượng bằng nhau
  • Giá trị dương: đối tượng này đứng sau đối tượng kia
public class Person implements Comparable<Person> {
    private String name;
    private int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public int compareTo(Person other) {
        return Integer.compare(this.age, other.age);  // Sắp xếp theo tuổi tăng dần
    }
}

Sau khi triển khai, việc sắp xếp trở nên đơn giản:

List<Person> people = new ArrayList<>();
people.add(new Person("Alice", 30));
people.add(new Person("Bob", 25));
Collections.sort(people);  // Giờ danh sách đã sắp xếp theo tuổi: Bob, Alice

Để so sánh chuỗi hoặc các trường Comparable khác, bạn có thể dùng phương thức compareTo() của chúng thay vì phép trừ: return this.name.compareTo(other.name);. Cách này an toàn hơn và xử lý đúng các trường hợp đặc biệt. Với trường int, hãy ưu tiên Integer.compare(a, b) thay cho a - b, vì phép trừ có thể gây tràn số với các giá trị cực lớn.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống xếp hạng phim sử dụng giao diện Comparable để sắp xếp phim theo điểm đánh giá. Bạn sẽ tạo lớp Movie có thể so sánh với các phim khác, nhờ đó phim tự động được sắp xếp từ điểm cao nhất đến thấp nhất.

Bạn sẽ tổ chức code trong hai tệp:

  • Movie.java: Tạo một lớp đại diện cho phim có thể so sánh với các phim khác. Một Movie có ba thuộc tính riêng tư: title (String), director (String) và rating (double, từ 0.0 đến 10.0). Thêm hàm khởi tạo để khởi tạo tất cả thuộc tính và các phương thức getter cho từng thuộc tính.

    Cho lớp Movie triển khai Comparable<Movie> và ghi đè phương thức compareTo(). Phim cần được sắp xếp theo điểm đánh giá theo thứ tự giảm dần (điểm cao nhất đứng đầu). Khi so sánh các số thực double, hãy dùng Double.compare() để so sánh an toàn: nhớ đảo thứ tự khi sắp xếp giảm dần!

    Ghi đè toString() để trả về: [title] by [director] - Rating: [rating]

  • Main.java: Tạo danh sách phim và sắp xếp chúng để sử dụng lớp Movie. Bạn sẽ nhận đầu vào gồm ba phim, mỗi phim trên một dòng riêng theo định dạng: title,director,rating

    Phân tích từng dòng để tạo các đối tượng Movie, thêm chúng vào một ArrayList, sau đó dùng Collections.sort() để sắp xếp danh sách. Nhờ phần triển khai Comparable, các phim sẽ tự động được sắp xếp theo điểm đánh giá!

    Sau khi sắp xếp, in từng phim trên một dòng riêng theo định dạng toString(). Phim có điểm cao nhất sẽ xuất hiện đầu tiên.

Bạn sẽ nhận đầu vào gồm ba dòng, mỗi dòng chứa dữ liệu phim theo định dạng: title,director,rating

Ví dụ, một dòng đầu vào có thể như sau: Inception,Christopher Nolan,8.8

Nhớ nhập java.util.ArrayList, java.util.Collections và java.util.Scanner vào tệp Main. Hãy chú ý cách triển khai Comparable cho phép bạn sắp xếp các đối tượng tùy chỉnh chỉ bằng một lần gọi phương thức, không cần bộ so sánh bổ sung!

Tự làm thử

import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Đọc ba dòng dữ liệu phim
        String line1 = scanner.nextLine();
        String line2 = scanner.nextLine();
        String line3 = scanner.nextLine();
        
        // TODO: Tạo một ArrayList để lưu các đối tượng Movie
        
        // TODO: Phân tích từng dòng (định dạng: title,director,rating)
        // Gợi ý: Dùng split(",") để tách các phần
        // Gợi ý: Dùng Double.parseDouble() cho rating
        
        // TODO: Tạo các đối tượng Movie và thêm vào danh sách
        
        // TODO: Sắp xếp danh sách bằng Collections.sort()
        
        // TODO: In ra từng phim (mỗi dòng một phim)
    }
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch Java online