Comparator và Comparable trong Java


Comparator và Comparable trong Java

Trong một danh sách, một mảng, khi muốn sắp xếp, ta phải áp dụng một số kỹ thuật cơ bản (Bubble sort, Quick sort, Insertion sort,…) để sắp xếp 1 danh sách. Thực tế, Java cung cấp cho bạn một hàm dùng để sắp xếp, bạn không cần phải tự mình xây dựng thuật toán sắp xếp nữa. Hàm này sẽ giúp bạn giải quyết các mảng, các danh sách có kiểu dữ liệu nguyên thủy hoặc Wrapper tương ứng. Hãy xem ví dụ sau:



Kết quả in ra màn hình như sau:
Như các bạn thấy, mảng arr đã được sắp xếp theo thứ tự tăng dần thông qua hàm Arrays.sort() và danh sách list đã được sắp xếp theo thứ tự tăng dần thông qua hàm Collections.sort(). Bạn chỉ cần thả một mảng/ danh sách vào hàm tương ứng để được sắp xếp
Vấn đề đặt ra: Nếu kiểu dữ liệu ngoài kiểu nguyên thủy và Wrapper tương ứng ra thì sao?
Ta có một trường hợp như sau:

Và kết quả là:

Vì sao lại như vậy nhỉ? Hãy đặt nghi vấn ngược xem nếu nó chạy được thì nó sẽ sắp xếp như thế nào? Khi nào thì một đối tượng A lớn hơn một đối tượng B? Tên của A đứng trước B, hay tuổi của A nhỏ hơn B? Chính vấn đề về việc định nghĩa một đối tượng lớn hơn đối tượng khác là nguyên nhân, vì mỗi đối tượng được thể hiện qua nhiều thuộc tính khác nhau (Ví dụ đối tượng Học sinh được thể hiện qua Tên, Tuổi) nên việc xét đối tượng nào lớn hơn phải phụ thuộc vào cách người sử dụng định nghĩa.
Và thế là, Comparable ra đời
COMPARABLE
Comparable cho phép chúng ta định nghĩa về một đối tượng lớn hơn so với đối tượng khác là như thế nào. Chúng ta sẽ implements interface Comparable vào class của đối tượng cần xét và override hàm compareTo(T obj). Để hiểu rõ về nó, hãy xem ví dụ sau:

Ta sẽ có quy ước sau: nếu this.age nhỏ hơn that.age trả về số âm, this.age = that.age trả về 0, this.age > that.age trả về số dương. Theo quy tắc trên, ta sẽ sắp xếp được danh sách theo thứ tự tăng dần. Kết quả trả về như sau:

Vấn đề đã được giải quyết! Thế nhưng, một vấn đề khác lại xuất hiện, xuất phát từ thực tế. Giả sử một giáo viên cần danh sách sắp xếp theo tên để gọi tên theo bảng chữ cái, hay một địa phương cần danh sách sắp xếp theo tuổi để lựa chọn thành phần đi khám nghĩa vụ quân sự. Comparable chỉ cung cấp một cách định nghĩa đối tượng lớn hơn đối tượng. Vì thế, Comparator sẽ giải quyết bài toán này.
COMPARATOR
Comparator là một interface giúp cho chúng ta giải quyết bài toán sắp xếp tùy vào những yêu cầu khác nhau. Chúng ta cần phải tạo một class implements Comparator, override hàm compare(T obj1, T obj2). Sau đó trong hàm Arrays.sort(), ngoài việc thêm vào một danh sách, bạn sẽ thêm đối tượng thuộc class ban nãy bạn đã tạo.
Để đơn giản, mời bạn xem ví dụ bên dưới:

Kết quả như sau:

Các quy ước để chuỗi tăng dần giống như Comparator. Các bạn cố gắng đọc rồi suy ngẫm để hiểu thêm. Mình sẽ giải thích ngắn gọn về tư tưởng của Comparable và Comparator ở phần kết.
SO SÁNH GIỮA COMPARABLE VÀ COMPARATOR
1.     Comparable chỉ so sánh hai đối tượng theo một cách duy nhất, trong khi đó Comparator so sánh theo nhiều cách khác nhau
2.     Comparable nằm trong java.lang trong khi đó Comparator nằm trong java.util (java.lang là package mặc định, mang tính cơ bản. Còn java.util là package xem như tính năng mở rộng. Chi tiết java.util và java.lang xem tại đây: Sự khác biệt giữa java.lang và java.util)
3.     Trên phương diện người dùng, khi sử dụng không có bất kỳ sự thay đổi nào (Arrays.sort() vẫn giữ nguyên như kiểu nguyên thủy, Wrapper) trong khi đó Comparator, người dùng phải sử dụng một class implements Comparator
4.     Trong Comparable, class của đối tượng trong danh sách cần sắp xếp bị thay đổi (cụ thể là implements Comparable và override phương thức compareTo()) trong khi đó Comparator, class của đối tượng không bị thay đổi.
GIẢI THÍCH VỀ MẶT Ý TƯỞNG
Khi chúng ta sắp xếp các đối tượng, chúng ta sẽ phải xác định việc so sánh đối tượng (cái nào lớn hơn cái nào). Comparable giúp chúng ta định nghĩa điều đó. Đó cũng có thể xem như là một định nghĩa mặc định, được cài đặt trực tiếp (phía người thực hiện). Thế nhưng, trong đời sống thực tế, có thể có nhiều cách định nghĩa khác nhau. Vậy nên, trong quá trình sắp xếp, chúng ta sẽ truyền vào một Comparator, chính là đưa vào cách chúng ta (phía người dùng) định nghĩa về nó, để nó hiểu và sắp xếp theo cách đó. Lưu ý rằng Comparable và Comparator chỉ là cách so sánh, không phải là cách sắp xếp, dễ thấy nhất đó là hàm compareTo() của lớp String, nó cũng thuộc Comparable, và đó chỉ là cách so sánh. Cách sắp xếp như thế nào, nó thuộc về Arrays.sort() và Collections.sort(). Vậy nên, khi nhắc đến Comparable hay Comparator, bạn hãy nhớ đặc điểm của đó là định nghĩa so sánh nhé, và nó gắn liền với việc sắp xếp.
Và đó cũng chính là tổng kết của bài viết này. Thấy hay thì cho 1 like nhá <3!
Nội dung bài viết thuộc về Lê Công Diễn.

Người viết: Lê Công Diễn
Mang đi nhớ ghi nguồn

Nhận xét

Đăng nhận xét

Bài đăng phổ biến từ blog này

Deploy project Springboot MIỄN PHÍ sử dụng Render

Ứng dụng Mã hóa bất đối xứng (Asymmetric cryptography) vào Chữ ký số (Digital Signature)

API và HTTP - Một số khái niệm cơ bản cần biết về Web (Phần 2)