|
|
在 Collection 中談到TreeSet,會將你加入的物件進行排序,預設使用自然順序(Natural order)。例如: Set set = new TreeSet();
set.add("Justin"); set.add("Bush"); set.add("Momor"); System.out.println(set); 最後顯示的順序是[Bush, Justin, Momor]。如果你定義了Student類別: public class Student {
private String name; private int score; public Student(String name, int score) { this.name = name; this.score = score; } public String getName() { return name; } public int getScore() { return score; } public String toString() { return "Student [name=" + name + ", score=" + score + "]"; } } 然後這麼新增至TreeSet: Set set = new TreeSet();
set.add(new Student("Justin", 96)); set.add(new Student("Bush", 88)); set.add(new Student("Momor", 93)); System.out.println(set); 那在第二次新增Student實例時會引發ClassCastException的錯誤,先不論引發例外的原因為何,你並沒有告訴TreeSet,是要根據學生名稱,還是根據學生分數排序不是嗎? 可以試著讓Student實作Comparable介面: public class Student implements Comparable<Student> { private String name; private int score; public Student(String name, int score) { this.name = name; this.score = score; } public String getName() { return name; } public int getScore() { return score; } public String toString() { return "Student [name=" + name + ", score=" + score + "]"; } public int compareTo(Student other) { return this.score - other.score; } } Comparable有個compareTo()方法要實作,它會傳 入一個物件,你要傳回大於0、0或小於0的數。傳回大於0表示,傳入的物件順序上比目前物件大,應該排在後面,傳回0表示兩個物件順序上相等,傳回小於0 表示傳入的物件順序上比目前物件小,應該排在前面。就上例而言,會根據學生的分數由小到大排序。重新執行上面新增學生的程式片段,結果會顯示 [Student [name=Bush, score=88], Student [name=Momor, score=93], Student [name=Justin, score=96]]。 所以,當你使用TreeSet新增物件時,TreeSet會預期新增的物件都必須實作Comparable介面,在嘗試比較兩個物件時,其實就會試著將新 增的物件轉型(Cast)為Comparable型態,再用compareTo()進行比較。所以先前未實作Comparable的Student在新增 至TreeSet時,就會引發ClassCastException,原因就在此。 排序時根據物件上的Comparable介面定義之順序,就稱之自然順序(Natural order)。事實上,String就實作了Comparable介面,所以你可以直接將字串加入TreeSet,就是這個原因。 然而有時候,你並不是有辦法讓物件實作Comparable介面,例如String就是了,你不能改變String,也不能繼承String並實作 Comparable介面,若你想讓TreeSet排序字串時以與先前相反的順序該如何?你可以在建立TreeSet時,指定一個Comparator實 作物件。例如: Set set = new TreeSet(new Comparator<String>() {
public int compare(String s1, String s2) { return -s1.compareTo(s2); } }); set.add("Justin"); set.add("Bush"); set.add("Momor"); System.out.println(set); Comparator有一個compare()方法要實作,它會傳入兩個物件,同樣地,你要傳回你要傳回大於0、0或小於0的數。傳回大於0表示,左邊傳入的物件順序上比右邊傳入物件大,應該排在後面,傳回0表示兩個物件順序上相等,傳回小於0表示左邊傳入的物件順序上比右邊傳入物件小,應該排在前面。上例會顯示[Momor, Justin, Bush]。 如果你不想用TreeSet排序,則可以將物件新增至List,再使用Collections的sort()方法進行排序。你可以使用自然順序。例如以下顯示[Bush, Justin, Momor]: List<String> list = new ArrayList<String>();
list.add("Justin"); list.add("Bush"); list.add("Momor"); Collections.sort(list); System.out.println(list); 或者是給定一個Comparator,例如以下顯示[Momor, Justin, Bush]: List<String> list = new ArrayList<String>();
list.add("Justin"); list.add("Bush"); list.add("Momor"); Collections.sort(list, new Comparator<String>() { public int compare(String s1, String s2) { return -s1.compareTo(s2); } }); System.out.println(list); |