Comparator interface trong Java

Comparator interface được sử dụng để sắp xếp thứ tự các object của các class do chúng ta tự định nghĩa. Một comparator object có khả năng so sánh hai object khác nhau dựa theo các tiêu chí mà nó tự định nghĩa.

public int compare(Object obj1, Object obj2):

Giả sử chúng ta có một mảng thuộc chứa các Student object có các thuộc tính như rollno, name, address, DOB v.v. và chúng ta cần sắp xếp mảng dựa trên Rollno hoặc name?

Phương pháp 1: Một cách tiếp cận rõ ràng là viết hàm sort () của riêng chúng ta bằng cách sử dụng một trong các thuật toán tiêu chuẩn. Thế nhưng giải pháp này yêu cầu chúng ta phải triển khai lại các thuật toán rất dài dòng.

Phương pháp 2: Sử dụng Comparator interface để định nghĩa cách so sánh giữa 2 Student object với nhau. Sau đó chúng ta có thể sử dụng Collections.sort() được cung cấp sẵn, method này cần nhận vào một Comparator Object được sử dụng trong quá trình nó chạy thuật toán sắp xếp đã được định nghĩa sẵn. 

public static <T> void sort(List<T> list, Comparator<? super T> c) {}

Giả sử mình tạo 2 class Sortbyroll và Sortbyname đều implement từ Comparator dùng để so sánh theo roll và name tương ứng

import java.util.*;
import java.lang.*;
import java.io.*;
 
// A class to represent a student.
class Student
{
    int rollno;
    String name, address;
 
    // Constructor
    public Student(int rollno, String name,
                               String address)
    {
        this.rollno = rollno;
        this.name = name;
        this.address = address;
    }
 
    // Used to print student details in main()
    public String toString()
    {
        return this.rollno + " " + this.name +
                           " " + this.address;
    }
}
 
class Sortbyroll implements Comparator<Student>
{
    // Used for sorting in ascending order of
    // roll number
    public int compare(Student a, Student b)
    {
        return a.rollno - b.rollno;
    }
}
 
class Sortbyname implements Comparator<Student>
{
    // Used for sorting in ascending order of
    // name
    public int compare(Student a, Student b)
    {
        return a.name.compareTo(b.name);
    }
}
 
// Driver class
class Main
{
    public static void main (String[] args)
    {
        ArrayList<Student> ar = new ArrayList<Student>();
        ar.add(new Student(111, "bbbb", "london"));
        ar.add(new Student(131, "aaaa", "nyc"));
        ar.add(new Student(121, "cccc", "jaipur"));
 
        System.out.println("Unsorted");
        for (int i=0; i<ar.size(); i++)
            System.out.println(ar.get(i));
 
        Collections.sort(ar, new Sortbyroll());
 
        System.out.println("\nSorted by rollno");
        for (int i=0; i<ar.size(); i++)
            System.out.println(ar.get(i));
 
        Collections.sort(ar, new Sortbyname());
 
        System.out.println("\nSorted by name");
        for (int i=0; i<ar.size(); i++)
            System.out.println(ar.get(i));
    }
}

Output

Unsorted
111 bbbb london
131 aaaa nyc
121 cccc jaipur

Sorted by rollno
111 bbbb london
121 cccc jaipur
131 aaaa nyc

Sorted by name
131 aaaa nyc
111 bbbb london
121 cccc jaipur

Các bạn có thể thay đổi thứ tự so sánh để đạt được một kết quả sắp xếp giảm dần thay vì tăng dần như ví dụ trên.

Đoạn mã dưới đây cho phép chúng ta sắp xếp giảm dần theo rollno.

class Sortbyroll implements Comparator<Student>
{
    // Used for sorting in ascending order of
    // roll number
    public int compare(Student a, Student b)
    {
        return b.rollno - a.rollno;
    }
}

Trong ví dụ trên chúng ta đã biết cách triển khai Comparator để sắp xếp các Student theo thứ tự tăng, giảm dần theo rollno, name. Nhưng nếu yêu cầu được thay đổi nho nhỏ rằng sắp xếp các Student theo name, đối với các Student cùng name thì so sánh theo Age.

Từ yêu cầu trên chúng ta có thể thấy rằng việc so sánh giờ đây phải được chia thành 2 cấp, đầu tiên là name sau đó đến age

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Comparator;
 
class Student {
 
    // instance member variables
    String Name;
    int Age;
 
    // parameterized constructor
    public Student(String Name, Integer Age) {
        this.Name = Name;
        this.Age = Age;
    }
 
    public String getName() {
        return Name;
    }
 
    public void setName(String Name) {
        this.Name = Name;
    }
 
    public Integer getAge() {
        return Age;
    }
 
    public void setAge(Integer Age) {
        this.Age = Age;
    }
 
    // overriding toString() method
    @Override
    public String toString() {
        return "Customer{" + "Name=" + Name + ", Age=" + Age + '}';
    }
 
    static class CustomerSortingComparator implements Comparator<Student> {
 
        @Override
        public int compare(Student customer1, Student customer2) {
 
            // for comparison
            int NameCompare = customer1.getName().compareTo(customer2.getName());
            int AgeCompare = customer1.getAge().compareTo(customer2.getAge());
 
            // 2-level comparison using if-else block
            if (NameCompare == 0) {
                return ((AgeCompare == 0) ? NameCompare : AgeCompare);
            } else {
                return NameCompare;
            }
        }
    }
 
    public static void main(String[] args) {
 
        // create ArrayList to store Student
        List<Student> al = new ArrayList<>();
 
        // create customer objects using constructor initialization
        Student obj1 = new Student("Ajay", 27);
        Student obj2 = new Student("Sneha", 23);
        Student obj3 = new Student("Simran", 37);
        Student obj4 = new Student("Ajay", 22);
        Student obj5 = new Student("Ajay", 29);
        Student obj6 = new Student("Sneha", 22);
 
        // add customer objects to ArrayList
        al.add(obj1);
        al.add(obj2);
        al.add(obj3);
        al.add(obj4);
        al.add(obj5);
        al.add(obj6);
 
        // before Sorting arraylist: iterate using Iterator
        Iterator<Student> custIterator = al.iterator();
 
        System.out.println("Before Sorting:\n");
        while (custIterator.hasNext()) {
            System.out.println(custIterator.next());
        }
 
        // sorting using Collections.sort(al, comparator);
        Collections.sort(al, new CustomerSortingComparator());
 
        // after Sorting arraylist: iterate using enhanced for-loop
        System.out.println("\n\nAfter Sorting:\n");
        for (Student customer : al) {
            System.out.println(customer);
        }
    }
}

Output

Before Sorting:

Customer{Name=Ajay, Age=27}
Customer{Name=Sneha, Age=23}
Customer{Name=Simran, Age=37}
Customer{Name=Ajay, Age=22}
Customer{Name=Ajay, Age=29}
Customer{Name=Sneha, Age=22}


After Sorting:

Customer{Name=Ajay, Age=22}
Customer{Name=Ajay, Age=27}
Customer{Name=Ajay, Age=29}
Customer{Name=Simran, Age=37}
Customer{Name=Sneha, Age=22}
Customer{Name=Sneha, Age=23}

Nguồn tham khảo

https://www.geeksforgeeks.org/comparator-interface-java/

5 2 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x