Collections 的排序【轉】- -
在使用 Java Collections Framework 時,必須知道 Collections
類中的變量是哪些。這個類包含大量支持集合操作的靜態方法。在這里,我們不會對所有方法進行介紹,因為您可以自己閱讀 API,但是我們將介紹兩個經常出現在 Java 代碼中的方法:
第一個方法允許將一個集合的內容復制到另一個集合,如下所示:
List source = new ArrayList();
source.add("one");
source.add("two");
List target = new ArrayList();
target.add("three");
target.add("four");
Collections.copy(target, source);
System.out.println(target);
該代碼將 source
復制到 target
中。目標代碼的大小必須與源代碼的大小相同,這樣,就無法將 List
復制到空的 List
中。
sort()
方法元素歸類成其自然順序。所有元素都必須實現 Comparable
接口,這樣,它們就可以相互比較。像 String
這樣的內置類也已經創建。因此,對于一組字符串而言,可以使用以下代碼按照字典順序的升序順序對字符串進行排序:
List strings = new ArrayList();
strings.add("one");
strings.add("two");
strings.add("three");
strings.add("four");
Collections.sort(strings);
System.out.println(strings);
您將在控制臺中獲得 [four, one, three, two]
。但是現在可以對創建的類進行分類嗎?可以對 Adult
進行分類。首先要讓類進行相互比較:
public class Adult extends Person implements Comparable {
...
}
然后要重寫 compareTo()
來比較兩個 Adult
實例。我們將保持我們的例子在比較方面的簡單性,所以該例不會進行太多的比較操作:
public int compareTo(Object other) {
final int LESS_THAN = -1;
final int EQUAL = 0;
final int GREATER_THAN = 1;
Adult otherAdult = (Adult) other;
if ( this == otherAdult ) return EQUAL;
int comparison = this.firstname.compareTo(otherAdult.firstname);
if (comparison != EQUAL) return comparison;
comparison = this.lastname.compareTo(otherAdult.lastname);
if (comparison != EQUAL) return comparison;
return EQUAL;
}
任何小于 0 的數字都意味著“小于”,但是 -1 是表示這個意思一個很好用的值。與此類似,用 1 表示“大于”也很方便。正如您可以看到的,0 則意味著“等于”。以這種方式比較兩個對象顯然是一個手動過程。您必須遍歷實例變量并比較每個變量。在這種情況下,我們要比較名和姓,并根據姓氏有效地對人們進行排序。但是您應該能夠明白為什么我們的例子過于簡單。每個 Adult
都只有一個名和姓。如果想進行深層的比較,那么必須比較每個 Adult
的 Wallet
,以查看它們是否相等,這可能意味著我們必須在 Wallet
和其余對象上實現 compareTo()
。此外,為了正確進行比較,無論何時重寫 compareTo()
,都必須確保該比較與 equals()
是一致的。我們沒有實現 equals()
,所以不用擔心要與它一致,但我們可以做到這一點。事實上,在返回 EQUAL
之前,我已經看到包含類似以下代碼行的代碼:
assert this.equals(otherAdult) : "compareTo inconsistent with equals.";
比較對象的其他方法是:提取 compareTo()
中的算法,將其放入 Comparator
類型的對象中,然后對將分類的集合調用 Collections.sort()
和 Comparator
,如下所示:
public class AdultComparator implements Comparator {
public int compare(Object object1, Object object2) {
final int LESS_THAN = -1;
final int EQUAL = 0;
final int GREATER_THAN = 1;
if ((object1 == null) ;amp;amp (object2 == null))
return EQUAL;
if (object1 == null)
return LESS_THAN;
if (object2 == null)
return GREATER_THAN;
Adult adult1 = (Adult) object1;
Adult adult2 = (Adult) object2;
if (adult1 == adult2)
return EQUAL;
int comparison = adult1.firstname.compareTo(adult2.firstname);
if (comparison != EQUAL)
return comparison;
comparison = adult1.lastname.compareTo(adult2.lastname);
if (comparison != EQUAL)
return comparison;
return EQUAL;
}
}
public class CommunityApplication {
public static void main(String[] args) {
Adult adult1 = new Adult();
adult1.setFirstname("Bob");
adult1.setLastname("Smith");
Adult adult2 = new Adult();
adult2.setFirstname("Al");
adult2.setLastname("Jones");
List adults = new ArrayList();
adults.add(adult1);
adults.add(adult2);
Collections.sort(adults, new AdultComparator());
System.out.println(adults);
}
}
在控制臺窗口中,應該看到以某種順序排列的“Al Jones”和“Bob Smith”。
使用第二種方法是有一些好的理由的。技術方面的理由已經超出了本文的討論范圍。不過,從好的 OOD 的角度來看,將比較代碼隔離到另一個對象中,而不是為每個 Adult
提供將自身與其他對象比較的能力是一個好主意。然而,因為這正是 equals()
要做的事,所以即使結果是布爾值,對于每種方法而言,那些仍然是一些好參數。
何時應該使用特殊類型的集合?這是一個由您做出的判斷決定,而且,正是因為這類的決定,您希望像一位編程人員那樣付出很多。
盡管許多專業人士相信,沒有太多關于在任一給定情況下使用哪些類的硬性規定。以我的個人經驗而論,大多數時間里,我使用集合、ArrayList
或 HashMap
(請記住,Map
不是真正的集合)獲得了成功。您自己去體驗可能也會有同樣的效果。以下是一些經驗法則,其中的一些顯然要好于另外一些:
- 在認為自己需要一個集合時,從使用
List
開始,然后讓代碼告訴您是否需要另一種類型的集合。
- 如果需要惟一的一組什么東西,那么請使用
Set
。
- 在遍歷集合時,如果迭代順序很重要,則使用可用的
Tree...
風格的集合。
- 避免使用
Vector
,除非需要利用其同步功能。
- 直到(除非)性能出現問題,否則不用擔心最優化。
集合是 Java 語言的最強大的一個方面。不要害怕使用集合,但要提防“轉向”。例如,以下是一個從 Array
轉換到 ArrayList
的一個便利方法:
Adult adult1 = new Adult();
Adult adult2 = new Adult();
Adult adult3 = new Adult();
List immutableList = Arrays.asList(new Object[] { adult1, adult2, adult3 });
theList.add(new Adult());
這個代碼拋出一個 UnsupportedOperationException
,因為由 Arrays.asList()
返回的 List
是不可變的。而您又無法將新的元素添加到不可變的 List
中,所以必須留心一點。
posted on 2005-11-30 12:00
Java&Inter 閱讀(695)
評論(0) 編輯 收藏 所屬分類:
Java技術