Sắp xếp tự nhiên trong Java với Comparable

Khái niệm Comparable và sắp xếp tự nhiên

Comparable là một interface cốt lõi trong Java, nằm trong gói java.lang, cho phép các đối tượng tự định nghĩa thứ tự sắp xếp mặc định của chính mình.

Sắp xếp tự nhiên là cách thức sắp xếp dựa trên đặc tính vốn có của dữ liệu:

  • Số học: Theo giá trị tăng dần hoặc giảm dần
  • Ký tự: Theo thứ tự bảng chữ cái Unicode
  • Thời gian: Theo mốc thời gian từ trước đến sau

Cấu trúc interface Comparable

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

Phương thức compareTo trả về giá trị nguyên biểu thị quan hệ so sánh:

Giá trị âmĐối tượng hiện tại nhỏ hơn đối tượng truyền vào
0Hai đối tượng bằng nhau
Giá trị dươngĐối tượng hiện tại lớn hơn đối tượng truyền vào

Triển khai Comparable trong thực tế

Khi một lớp triển khai Comparable, nó có thể được sử dụng trực tiếp với:

  • Arrays.sort() cho mảng
  • Collections.sort() hoặc List.sort() cho danh sách
  • Các cấu trúc dữ liệu có thứ tự như TreeSet, TreeMap

Ví dụ: Sắp xếp nhân viên theo mức lương

public class NhanVien implements Comparable<NhanVien> {
    private String hoTen;
    private double luong;
    private int namKinhNghiem;

    public NhanVien(String hoTen, double luong, int namKinhNghiem) {
        this.hoTen = hoTen;
        this.luong = luong;
        this.namKinhNghiem = namKinhNghiem;
    }

    @Override
    public int compareTo(NhanVien nvKhac) {
        // Sắp xếp tăng dần theo lương
        return Double.compare(this.luong, nvKhac.luong);
        
        // Hoặc sắp xếp giảm dần:
        // return Double.compare(nvKhac.luong, this.luong);
    }

    @Override
    public String toString() {
        return String.format("%s - %.1f triệu (%d năm KN)", 
            hoTen, luong, namKinhNghiem);
    }
}

Sử dụng trong chương trình

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

public class QuanLyNhanSu {
    public static void main(String[] args) {
        List<NhanVien> danhSach = new ArrayList<>();
        danhSach.add(new NhanVien("Nguyễn Văn A", 15.5, 3));
        danhSach.add(new NhanVien("Trần Thị B", 12.0, 2));
        danhSach.add(new NhanVien("Lê Văn C", 18.0, 5));

        System.out.println("Trước khi sắp xếp:");
        danhSach.forEach(System.out::println);

        Collections.sort(danhSach);

        System.out.println("\nSau khi sắp xếp theo lương:");
        danhSach.forEach(System.out::println);
    }
}

Sắp xếp theo nhiều tiêu chí

Khi cần sắp xếp phức tạp hơn, có thể kết hợp nhiều trường:

@Override
public int compareTo(NhanVien nvKhac) {
    // Ưu tiên năm kinh nghiệm giảm dần, nếu bằng thì xét lương tăng dần
    int soSanhKN = Integer.compare(nvKhac.namKinhNghiem, this.namKinhNghiem);
    if (soSanhKN != 0) {
        return soSanhKN;
    }
    return Double.compare(this.luong, nvKhac.luong);
}

Hoặc sử dụng phương thức tiện ích từ Java 8:

@Override
public int compareTo(NhanVien nvKhac) {
    return Comparator.comparingInt((NhanVien nv) -> -nv.namKinhNghiem)
                     .thenComparingDouble(nv -> nv.luong)
                     .compare(this, nvKhac);
}

Lưu ý quan trọng

  • Quan hệ so sánh phải nhất quán: nếu a.compareTo(b) > 0 thì b.compareTo(a) < 0
  • Nên đảm bảo tính tương đương với equals(): nếu compareTo trả về 0 thì equals nên trả về true
  • Comparable chỉ hỗ trợ một quy tắc sắp xếp mặc định; muốn linh hoạt hơn hãy dùng Comparator

Thẻ: Java Comparable sorting Collections Java 8

Đăng vào ngày 28 tháng 9 lúc 01:25