walterwing |
|
|||
日歷
統計
導航常用鏈接留言簿(1)隨筆分類隨筆檔案搜索最新評論
閱讀排行榜評論排行榜 |
本篇內容主要來自Introduction to Collections (http://java.sun.com/docs/books/tutorial/collections/intro/index.html),僅為個人學習和參考之用
集合框架主要包括三部分內容:接口,實現,算法。下面分別來介紹 一. 接口 ![]() 上圖所示即為java中集合框架所包含的各種接口。可以發現Map(包括SortedMap)是不繼承自Collection的,這是因為Map不同于一 般的Collection,只是一堆元素的結合,Map的特點在于他存儲的是一個個“鍵-值”對,因此他不繼承Collection。但是,Map本身還 是提供了很多Collection-views的方法,從而使其能像其他Collection一樣進行各種操作。具體將在后面介紹。 下面來簡要介紹一下各個接口: ·Collection:是整個collection hierarchy的root,一個Collection代表一組對象的集合,這些對象稱為該Collection的元素(element)。 Collection根據不同的性質可以進行不同的劃分,比如允許有重復元素的,不允許的;元素有順序的,沒有順序的……等等。當時Java platform并不提供Collection的直接實現類,而是根據上面提到的不同性質,定義了繼承自Collection的多個子接口,比如下面將要 提到的Set,List等 ·Set:不允許有重復元素的Collection。這個接口是以數學中的集合概念抽象出來的。 ·List:允許有重復元素,并且元素有順序的Collection ·Queue:除了提供基本的Collection操作外,還提供了插入、提取、檢查操作。Queue通常采用FIFO機制,但也有特例,比如 priority queue,就支持通過提供的Comparator或者元素自己的natural ordering(指實現了Comparable接口)對內部元素進行排序。 ·Map:存儲“鍵-值”對。Map不允許重復的key,同時一個key最多指向一個value。 ·SortedSet:對內部元素進行升序排列的Set。當然了,既然本身已經排好序,那么SortedSet也就相應的提供了一些額外的操作來利用排好的序列。 ·SortedMap:對鍵值進行升序排列的Map。典型的例子:字典,電話簿 下面就來詳細介紹各個接口。 1. Collection 下面是Collection接口的代碼: public interface Collection<E> extends Iterable<E> {
// Basic operations int size(); boolean isEmpty(); boolean contains(Object element); boolean add(E element); //optional boolean remove(Object element); //optional Iterator<E> iterator(); // Bulk operations boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c); //optional boolean removeAll(Collection<?> c); //optional boolean retainAll(Collection<?> c); //optional void clear(); //optional // Array operations Object[] toArray(); <T> T[] toArray(T[] a); } Collection定義了身為一個集合類所應實現的所有方法。當然,其中一些是optional的,可以根據自己的情況選擇是否實現。但Java platform所提供的general-purpose的Collection實現類,是實現了這里定義的所有方法的。 遍歷一個Collection的方法有兩種: ·使用for循環 for (Object o : collection)
System.out.println(o); ·使用Iterator public interface Iterator<E> {
boolean hasNext(); E next(); void remove(); //optional } 在每個Collection的實現類內部都有一個非靜態成員類來實現Iterator接口。 有兩種情況,是必須使用Iterator而不能用for循環的: ·當需要在遍歷的同時刪除元素時。因為Iterator的remove()方法是遍歷過程中修改Collection的唯一安全的方法。 ·Iterate over multiple collections in parallel. - 這種情況我沒見過 下面一段代碼展示了如何在遍歷期間刪除元素: static void filter(Collection<?> c) {
for (Iterator<?> it = c.iterator(); it.hasNext(); ) if (!cond(it.next())) it.remove(); } 關于Collection接口定義的批量處理操作,沒什么特別的,知道就行了,需要的時候拿來用:
Object[] a = c.toArray();
String[] a = c.toArray(new String[0]);
第二種方式其實是對<T> T[] toArray(T[] a);的一種特殊用法。具體參加API doc。 2. Set 首先還是要強調的是Set不允許有重復的元素。 下面是Set接口的代碼: public interface Set<E> extends Collection<E> {
// Basic operations int size(); boolean isEmpty(); boolean contains(Object element); boolean add(E element); //optional boolean remove(Object element); //optional Iterator<E> iterator(); // Bulk operations boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c); //optional boolean removeAll(Collection<?> c); //optional boolean retainAll(Collection<?> c); //optional void clear(); //optional // Array Operations Object[] toArray(); <T> T[] toArray(T[] a); } 你會發現Set的接口內容和Collection是一樣的,的確一樣,因為Set只包含從Collection繼承過來的方法,并不包含其他方法;不僅沒加什么東西,反而還多了一個限制:不允許有重復的元素。 除此之外,Set還對equals和hashCode操作有嚴格的規定。要求即使是兩個不同的Set實現類,也能用equals來進行有意義的比較。比如,如果有兩個不同的Set實現類的實例,他們包含的元素相同,那么equals比較的結果就是這兩個實例也是相等的。 Java platform提供了三種general-purpose的Set實現類: ·HashSet:用Hash Table來存放元素。效率最高(在這三個里面)。在遍歷時不能保證元素的順序。 ·TreeSet:用紅-黑樹來存放元素,有順序,元素按照值來排列。 ·LinkedHashSet:Hash table + linked list存放元素。按照元素的插入順序來排列元素。犧牲了一些空間,但保證了元素順序。 由于Set具有的不允許有重復元素的特性,我們可以用下面兩種方法來去除某Collection實例中的重復元素: Collection<Type> noDups = new HashSet<Type>(c);
Collection<Type> noDups = new LinkedHashSet<Type>(c);
第二種方法不僅去除重復元素,而且還保證元素的順序不會被打亂。 舉一個例子來說明Set的基本用法: public class FindDups {
public static void main(String[] args) { Set<String> s = new HashSet<String>(); for (String a : args) if (!s.add(a)) System.out.println("Duplicate detected: " + a); System.out.println(s.size() + " distinct words: " + s); } } 這個例子的關鍵在于 if(!s.add(a))這句,由于Set不允許有重復元素,因此當要加入的a在Set里已經存在時,將不會被再次加入,此時add方法將返回false。 如果我們使用如下命令進行測試: java FindDups i came i saw i left 將得到下列結果: Duplicate detected: i
Duplicate detected: i 4 distinct words: [i, left, saw, came] 額外提一句,用Set來定義s而不是具體的實現類HashSet,是一個比較好的編程習慣,它是我們能夠不受約束的改變具體的實現類。 比如,如果我們需要按字母順序輸出的話,那么就可以使用TreeSet來代替HashSet,從而得到下面結果: java FindDups i came i saw i left
Duplicate detected: i Duplicate detected: i 4 distinct words: [came, i, left, saw] 關于Set的批量操作,更加顯示了Set是作為數學概念上集合的抽象的特性:
Set<Type> symmetricDiff = new HashSet<Type>(s1);
symmetricDiff.addAll(s2); Set<Type> tmp = new HashSet<Type>(s1); tmp.retainAll(s2)); symmetricDiff.removeAll(tmp); 注意在上面的代碼段中,我們沒有破壞s1、s2中的元素。這也是編程中的一個小技巧。 關于Set轉換成數組的操作,與Collection接口是完全一樣的,不需再介紹。
|
![]() |
|
Copyright © This is Wing | Powered by: 博客園 模板提供:滬江博客 |