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 |
| 0 | Hai đố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ảngCollections.sort()hoặcList.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) > 0thìb.compareTo(a) < 0 - Nên đảm bảo tính tương đương với
equals(): nếucompareTotrả về 0 thìequalsnê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