Java - Làm thế nào để sử dụng Comparable?

Chào mừng các bạn lập trình viên Java! Hôm nay, chúng ta sẽ cùng lặn sâu vào thế giới kỳ diệu của giao diện Comparable. Đừng lo lắng nếu bạn là người mới bắt đầu lập trình - tôi sẽ hướng dẫn bạn từng bước, tương tự như tôi đã làm với hàng trăm học viên trong những năm dạy học của mình. Hãy lấy một ly đồ uống yêu thích của bạn, và cùng nhau bắt đầu hành trình thú vị này nhé!

Java - Comparable Interface in Java

Giao diện Comparable là gì?

Hãy tưởng tượng bạn đang sắp xếp kệ sách của mình. Bạn có thể muốn sắp xếp sách theo tựa đề, tác giả hoặc năm xuất bản. Trong thế giới Java, giao diện Comparable giống như một thư viện cá nhân của bạn, giúp bạn sắp xếp các đối tượng theo một thứ tự cụ thể.

Giao diện Comparable là một phần của gói java.lang, có nghĩa là nó tự động có sẵn trong tất cả các chương trình Java. Nó chỉ chứa một phương thức:

public interface Comparable<T> {
public int compareTo(T o);
}

Đừng để điều này làm bạn hoảng sợ! Chúng ta sẽ phân tích nó từng phần.

Hiểu về phương thức compareTo()

Phương thức compareTo() là trái tim của giao diện Comparable. Nó so sánh đối tượng hiện tại với một đối tượng khác và trả về một giá trị nguyên tố:

  • Nếu kết quả là âm, đối tượng hiện tại được coi là "nhỏ hơn" đối tượng khác.
  • Nếu kết quả là dương, đối tượng hiện tại được coi là "lớn hơn" đối tượng khác.
  • Nếu kết quả là không, các đối tượng được coi là bằng nhau.

Hãy cùng xem điều này trong một ví dụ đơn giản:

public class Student implements Comparable<Student> {
private String name;
private int age;

public Student(String name, int age) {
this.name = name;
this.age = age;
}

@Override
public int compareTo(Student otherStudent) {
return this.age - otherStudent.age;
}

// Phương thức getter, setter và toString()
}

Trong ví dụ này, chúng ta đang so sánh học sinh dựa trên tuổi của họ. Nếu chúng ta trừ tuổi của học sinh khác từ tuổi của học sinh hiện tại, chúng ta sẽ được:

  • Một số âm nếu học sinh hiện tại trẻ hơn
  • Một số dương nếu học sinh hiện tại lớn hơn
  • Không nếu họ cùng tuổi

Thực hiện Comparable trong các đối tượng tùy chỉnh

Bây giờ chúng ta đã hiểu cơ bản, hãy cùng tạo một ví dụ phức tạp hơn. Chúng ta sẽ tạo một lớp Book và sắp xếp sách theo năm xuất bản.

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Book implements Comparable<Book> {
private String title;
private String author;
private int publicationYear;

public Book(String title, String author, int publicationYear) {
this.title = title;
this.author = author;
this.publicationYear = publicationYear;
}

@Override
public int compareTo(Book otherBook) {
return this.publicationYear - otherBook.publicationYear;
}

@Override
public String toString() {
return title + " by " + author + " (" + publicationYear + ")";
}

public static void main(String[] args) {
List<Book> bookshelf = new ArrayList<>();
bookshelf.add(new Book("1984", "George Orwell", 1949));
bookshelf.add(new Book("To Kill a Mockingbird", "Harper Lee", 1960));
bookshelf.add(new Book("The Great Gatsby", "F. Scott Fitzgerald", 1925));

System.out.println("Trước khi sắp xếp: " + bookshelf);
Collections.sort(bookshelf);
System.out.println("Sau khi sắp xếp: " + bookshelf);
}
}

Khi bạn chạy chương trình này, bạn sẽ thấy:

Trước khi sắp xếp: [1984 by George Orwell (1949), To Kill a Mockingbird by Harper Lee (1960), The Great Gatsby by F. Scott Fitzgerald (1925)]
Sau khi sắp xếp: [The Great Gatsby by F. Scott Fitzgerald (1925), 1984 by George Orwell (1949), To Kill a Mockingbird by Harper Lee (1960)]

Thật tuyệt vời phải không? Chỉ với vài dòng mã, chúng ta đã tạo ra một cơ chế sắp xếp tùy chỉnh cho sách của mình!

Sắp xếp theo thứ tự ngược lại

Nhưng nếu chúng ta muốn sắp xếp sách từ mới đến cũ? Đừng lo lắng! Java cung cấp một phương thức Collections.reverseOrder() tiện lợi cho mục đích này.

Hãy thay đổi phương thức main của chúng ta:

public static void main(String[] args) {
List<Book> bookshelf = new ArrayList<>();
bookshelf.add(new Book("1984", "George Orwell", 1949));
bookshelf.add(new Book("To Kill a Mockingbird", "Harper Lee", 1960));
bookshelf.add(new Book("The Great Gatsby", "F. Scott Fitzgerald", 1925));

System.out.println("Trước khi sắp xếp: " + bookshelf);
Collections.sort(bookshelf);
System.out.println("Sau khi sắp xếp (cũ đến mới): " + bookshelf);
Collections.sort(bookshelf, Collections.reverseOrder());
System.out.println("Sau khi sắp xếp (mới đến cũ): " + bookshelf);
}

Bây giờ, khi bạn chạy chương trình, bạn sẽ thấy:

Trước khi sắp xếp: [1984 by George Orwell (1949), To Kill a Mockingbird by Harper Lee (1960), The Great Gatsby by F. Scott Fitzgerald (1925)]
Sau khi sắp xếp (cũ đến mới): [The Great Gatsby by F. Scott Fitzgerald (1925), 1984 by George Orwell (1949), To Kill a Mockingbird by Harper Lee (1960)]
Sau khi sắp xếp (mới đến cũ): [To Kill a Mockingbird by Harper Lee (1960), 1984 by George Orwell (1949), The Great Gatsby by F. Scott Fitzgerald (1925)]

Kết luận

Và thế là bạn đã học cách sử dụng giao diện Comparable để sắp xếp các đối tượng tùy chỉnh trong Java. Nhớ rằng, chìa khóa để thành thạo lập trình là luyện tập. Hãy thử tạo ra các lớp của riêng bạn và thực hiện Comparable theo các cách khác nhau. Có thể bạn sẽ sắp xếp danh sách phim theo đánh giá, hoặc danh sách công thức theo số lượng nguyên liệu.

Như tôi luôn nói với học sinh của mình, lập trình giống như nấu ăn - bạn có thể làm rối loạn ban đầu, nhưng với sự luyện tập, bạn sẽ tạo ra những kiệt tác trong tích tắc. Hãy tiếp tục lập trình, tiếp tục học hỏi, và quan trọng nhất, hãy vui vẻ!

Dưới đây là bảng tham khảo nhanh các phương thức chúng ta đã sử dụng:

Phương thức Mô tả
compareTo(T o) So sánh đối tượng này với đối tượng được chỉ định theo thứ tự
Collections.sort(List<T> list) Sắp xếp danh sách được chỉ định theo thứ tự tăng dần
Collections.sort(List<T> list, Comparator<? super T> c) Sắp xếp danh sách được chỉ định theo thứ tự được xác định bởi bộ so sánh được chỉ định
Collections.reverseOrder() Trả về một bộ so sánh đảo ngược thứ tự tự nhiên trên một bộ sưu tập các đối tượng

Chúc bạn lập trình vui vẻ!

Credits: Image by storyset