Bộ so sánh, sắp xếp tập hợp - 1

"Chào, Amigo!"

"Chào, Bilaabo!"

"Hôm nay chúng ta sẽ xem xét một chủ đề nhỏ nhưng thú vị và hữu ích: sắp xếp các tập hợp."

"Sắp xếp? Tôi đã nghe điều gì đó về điều đó."

"Từ lâu, mọi lập trình viên đều phải có khả năng viết các thuật toán sắp xếp. Đã có thể và phải viết chúng. Nhưng những ngày đó đã qua. Ngày nay, viết mã sắp xếp của riêng bạn bị coi là hình thức xấu, giống như viết lại bất kỳ thứ gì khác đã có được phát minh ra."

"Trong Java (và các ngôn ngữ lập trình khác), tính năng sắp xếp đã được triển khai.  Nhiệm vụ của bạn là học cách sử dụng đúng cách những gì đã tồn tại. "

"ĐƯỢC RỒI."

" Lớp trình trợ giúp Bộ sưu tập có một phương pháp sắp xếp tĩnh được sử dụng để sắp xếp các bộ sưu tập—hay chính xác hơn là danh sách. Các phần tử trong Bản đồ và Tập hợp không có thứ tự/chỉ mục, vì vậy không có gì để sắp xếp."

"Vâng, tôi nhớ. Tôi đã sử dụng phương pháp này một lần để sắp xếp một danh sách các số."

"Tuyệt. Nhưng phương pháp này mạnh hơn nhiều so với cái nhìn đầu tiên. Nó có thể sắp xếp không chỉ các số, mà còn bất kỳ đối tượng nào, dựa trên bất kỳ tiêu chí nào. Hai giao diện giúp phương pháp này thực hiện việc này: Có thể so sánh và Bộ so sánh . "

"Đôi khi bạn cần sắp xếp các đối tượng, không phải số. Ví dụ: giả sử bạn có một danh sách mọi người và bạn muốn sắp xếp họ theo độ tuổi. Chúng tôi có giao diện So sánh cho việc này."

"Trước tiên hãy để tôi chỉ cho bạn một ví dụ, và sau đó mọi thứ sẽ trở nên rõ ràng hơn:"

Ví dụ
public class Woman implements Comparable<Woman>
{
public int age;

public Woman(int age) {
this.age = age;
}

public int compareTo(Woman o)
{
return this.age - o.age;
}
}
Một ví dụ về cách nó có thể được sử dụng:
public static void main(String[] args )
{
ArrayList<Woman> women = new ArrayList<Woman>();
women.add(new Woman(18));
women.add(new Woman(21));
women.add(new Woman(5));

Collections.sort(women);
}

"Để sắp xếp các đối tượng, trước tiên bạn phải biết cách so sánh chúng. Đối với điều này, chúng tôi sử dụng Có thể so sánh. Giao diện Có thể so sánh là một giao diện chung, có nghĩa là nó chấp nhận một đối số kiểu. Nó chỉ có một phương thức chung: so sánhTo(T o). Phương thức này so sánh đối tượng hiện tại (this) và đối tượng được truyền dưới dạng đối số (o). Nói cách khác, chúng ta cần triển khai phương thức này trong lớp của mình và sau đó sử dụng nó để so sánh đối tượng hiện tại (this) với đối tượng được truyền. "

"Và so sánhTo hoạt động như thế nào? Tôi dự đoán rằng nó sẽ trả về đúng hoặc sai tùy thuộc vào việc đối tượng được truyền lớn hơn hay nhỏ hơn."

"Mọi thứ phức tạp hơn ở đây. Phương thức so sánh không trả về true/false. Thay vào đó, nó trả về một int. Điều này thực sự được thực hiện để đơn giản.

"Khi máy tính cần xác định xem một số có lớn hơn số khác hay không, nó chỉ cần lấy số thứ nhất trừ số thứ hai rồi xem kết quả. Nếu kết quả bằng 0 thì hai số bằng nhau. Nếu kết quả nhỏ hơn 0 , thì số thứ hai lớn hơn. Và nếu kết quả lớn hơn 0, thì số thứ nhất sẽ lớn hơn."

"Logic tương tự áp dụng ở đây. Theo đặc tả, phương thức so sánh phải trả về 0 nếu các đối tượng được so sánh bằng nhau. Nếu phương thức so sánh trả về một số lớn hơn 0, thì đối tượng của chúng ta lớn hơn đối tượng được truyền." phương thức trả về một số nhỏ hơn 0, thì 'cái này' nhỏ hơn đối tượng được truyền."

"Đó là một chút kỳ lạ."

"Có, nhưng nếu bạn đang so sánh các đối tượng chỉ đơn giản dựa trên một số thuộc tính số, thì bạn có thể chỉ cần trả về sự khác biệt giữa chúng bằng cách trừ đối tượng này với đối tượng kia. Giống như cách đã thực hiện trong ví dụ trên."

public int compareTo(Woman o)
{
return this.age - o.age;
}

"Tôi nghĩ tôi hiểu mọi thứ. Nhưng có lẽ không. Nhưng hầu như mọi thứ."

"Tuyệt. Bây giờ hãy xem xét một vấn đề thực tế hơn. Giả sử bạn đã viết một trang web tuyệt vời để sản xuất quần áo phụ nữ ở Trung Quốc. Bạn sử dụng lớp Phụ nữ để mô tả khách hàng của mình. Bạn thậm chí còn tạo một trang web có bảng nơi bạn có thể xem tất cả .Nhưng có một vấn đề…”

"Đối tượng Người phụ nữ của bạn không chỉ chứa tuổi mà còn có cả đống dữ liệu khác: tên, họ, chiều cao, cân nặng, số con, v.v."

"Bảng người dùng có rất nhiều cột và đây là câu hỏi: làm cách nào để bạn sắp xếp người dùng của mình theo các tiêu chí khác nhau? Theo cân nặng, theo tuổi, theo họ?"

"Hmm. Vâng, tôi thường thấy các bảng cho phép bạn sắp xếp theo cột. Vậy, bạn làm điều đó như thế nào?"

"Đối với điều này, chúng ta có giao diện thứ hai mà tôi muốn giới thiệu với các bạn hôm nay: giao diện Bộ so sánh. Nó cũng có một phương thức so sánh, nhưng cần hai đối số chứ không phải một: int so sánh(T o1, T o2). Đây là cách thực hiện làm:"

Ví dụ
public class Woman
{
public int age;
public int childrenCount;
public int weight;
public int height;
public String name;

public Woman(int age) {
this.age = age;
}
}
Một ví dụ về cách nó có thể được sử dụng:
public static void main(String[] args )
{
ArrayList<Woman> women = new ArrayList<Woman>();
women.add(new Woman(18));
women.add(new Woman(21));
women.add(new Woman(5));

Comparator<Woman> compareByHeight = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.height - o2.height;
}
};

Collections.sort(women, compareByHeight);
}

"Giao diện Bộ so sánh không ẩn logic so sánh đối tượng bên trong lớp của các đối tượng được so sánh. Thay vào đó, nó được triển khai trong một lớp riêng biệt."

"Vì vậy, tôi có thể tạo một số lớp triển khai giao diện Bộ so sánh và để mỗi lớp so sánh các thuộc tính khác nhau? Cân nặng ở một lớp, tuổi ở lớp khác và chiều cao ở lớp thứ ba?"

"Vâng, nó rất đơn giản và thuận tiện."

"Chúng tôi chỉ gọi phương thức Collections.sort , chuyển một danh sách các đối tượng và một đối tượng đặc biệt khác làm đối số thứ hai, thực hiện giao diện Bộ so sánh và cho bạn biết cách so sánh chính xác các cặp đối tượng trong quá trình sắp xếp."

"Hmm. Tôi nghĩ tôi hiểu mọi thứ. Hãy để tôi thử. Giả sử tôi cần sắp xếp người dùng theo trọng lượng. Nó sẽ như thế này:"

Ví dụ về sắp xếp người dùng theo trọng lượng:
Comparator<Woman> compareByWeight = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.weight - o2.weight;
}
};

Collections.sort(women, compareByWeight);

"Đúng chính xác."

"Tuyệt. Nhưng nếu tôi muốn sắp xếp theo thứ tự ngược lại thì sao?"

"Nghĩ đi, đáp án rất đơn giản!"

"Tôi hiểu rồi! Như thế này:"

Sắp xếp theo thứ tự tăng dần:
return o1.weight - o2.weight;
Sắp xếp theo thứ tự giảm dần:
return o2.weight – o1.weight;

"Được. Làm tốt lắm."

"Và nếu tôi muốn sắp xếp theo họ? Làm cách nào để sắp xếp các chuỗi, Bilaabo?"

"Lớp String đã triển khai phương thức so sánh. Bạn chỉ cần gọi nó:"

Ví dụ về sắp xếp người dùng theo tên:
Comparator<Woman> compareByName = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.name.compareTo(o2.name);
}
};

Collections.sort(women, compareByName);

"Đó là một bài học tuyệt vời, Bilaabo. Cảm ơn bạn rất nhiều."

"Và cảm ơn bạn, bạn của tôi!"