比較器,排序集合 - 1

“嗨,阿米戈!”

“嗨,比拉博!”

“今天我們將研究一個小而有趣且有用的主題:對集合進行排序。”

“分院?我聽說過。”

“很久以前,每個程序員都必須能夠編寫排序算法。能夠並且必須編寫它們。但那些日子已經過去了。今天,編寫自己的排序代碼被認為是一種糟糕的形式,就像重寫任何已經存在的東西一樣被發明了。”

“在 Java(和其他編程語言)中,已經實現了排序。 你的任務是學習如何正確使用已經存在的東西。

“好的。”

Collections helper 類有一個靜態排序方法,用於對集合進行排序——或者更準確地說,列表。Maps 和 Sets 中的元素沒有順序/索引,所以沒有什麼可排序的。”

“是的,我記得。我曾經用這種方法對數字列表進行排序。”

“太棒了。但是這個方法比乍看起來要強大得多。它不僅可以對數字進行排序,還可以根據任何標準對任何對象進行排序。有兩個接口可以幫助該方法做到這一點: Comparable 和 Comparator

“有時你需要對對象而不是數字進行排序。例如,假設你有一個人的列表,你想按年齡對他們進行排序。我們為此提供了 Comparable 接口。

“讓我先給你舉個例子,然後一切都會變得更清楚:”

例子
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;
}
}
如何使用它的示例:
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);
}

“要對對象進行排序,您必須首先知道如何比較它們。為此,我們使用 Comparable。Comparable接口是泛型的,這意味著它接受類型參數。它只有一個泛型方法:compareTo(To)。這個方法比較當前對象(this)和作為參數傳遞的對象(o)。換句話說,我們需要在我們的類中實現這個方法,然後用它來比較當前對象(this)和傳遞的對象。 “

“compareTo 是如何工作的?我預計它會返回 true 或 false,這取決於傳遞的對像是更大還是更小。”

“這裡的事情比較棘手。compareTo 方法不返回 true/false。相反,它返回一個 int。這樣做實際上是為了簡單起見。

“當計算機需要確定一個數是否大於另一個數時,它只需從第一個數中減去第二個數,然後查看結果。如果結果為 0,則兩個數相等。如果結果小於零,則第二個數更大。如果結果大於零,則第一個數更大。”

“同樣的邏輯也適用於此。根據規範,如果比較的對象相等,compareTo 方法必須返回零。如果 compareTo 方法返回大於零的數字,那麼我們的對像大於傳遞的對象。“如果 compareTo方法返回一個小於零的數字,然後'this'小於傳遞的對象。”

“這有點奇怪。”

“是的,但如果你只是簡單地根據一些數字屬性來比較對象,那麼你可以通過一個減去另一個來返回它們之間的差異。就像上面例子中所做的那樣。”

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

“我想我什麼都懂。但也許不是。但幾乎所有。”

“太好了。現在讓我們考慮一個更實際的問題。假設你寫了一個很酷的網站,用於在中國製作女裝。你使用 Woman 類來描述你的客戶。你甚至製作了一個帶有表格的網頁,你可以在其中看到所有這些.但是有一個問題……”

“您的 Woman 對像不僅包含年齡,還包含一大堆其他數據:名字、姓氏、身高、體重、孩子數量等。”

“用戶表有很多列,問題來了:如何根據各種標準對用戶進行排序?按體重、年齡、姓氏?”

“嗯。是的,我經常看到可以讓你按列排序的表格。那麼,你是怎麼做到的?”

“為此,我們有我今天想告訴你的第二個接口:Comparator 接口。它也有一個比較方法,但它需要兩個參數,而不是一個:int compare(T o1, T o2)。這是它的方式作品:”

例子
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;
}
}
如何使用它的示例:
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);
}

“Comparator 接口不會將對像比較邏輯隱藏在被比較對象的類中。相反,它是在一個單獨的類中實現的。”

“所以,我可以創建幾個實現 Comparator 接口的類,讓每個類比較不同的屬性?一個是體重,另一個是年齡,第三個是身高?”

“是的,非常簡單方便。”

“我們只是調用Collections.sort方法,將對象列表和另一個特殊對像作為第二個參數傳遞,它實現了Comparator接口並告訴您如何在排序過程中正確比較對像對。”

“嗯,我想我都明白了,我試試看,假設我需要按權重對用戶進行排序,大概是這樣的:”

按權重排序用戶示例:
Comparator<Woman> compareByWeight = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.weight - o2.weight;
}
};

Collections.sort(women, compareByWeight);

“對,就是這樣。”

“很好。但是如果我想倒序排序怎麼辦?”

“想想看,答案很簡單!”

“我明白了!像這樣:”

按升序排序:
return o1.weight - o2.weight;
降序排列:
return o2.weight – o1.weight;

“對。幹得好。”

“如果我想按姓氏排序?我該如何對字符串排序,Bilaabo?”

“String 類已經實現了 compareTo 方法。您只需調用它:”

按名稱對用戶進行排序的示例:
Comparator<Woman> compareByName = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.name.compareTo(o2.name);
}
};

Collections.sort(women, compareByName);

“這是一個很好的教訓,Bilaabo。非常感謝你。”

“謝謝你,我的朋友!”