JAVA的容器ListMapSet
Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
Map
├Hashtable
├HashMap
└WeakHashMap
Collection接口
Collection是最基本的集合接口一個Collection代表一組Object即Collection的元素(Elements)一些 Collection允許相同的元素而另一些不行一些能排序而另一些不行Java SDK不提供直接繼承自Collection的類Java SDK提供的類都是繼承自Collection的子接口如List和Set
所有實現Collection接口的類都必須提供兩個標准的構造函數無參數的構造函數用於創建一個空的Collection有一個 Collection參數的構造函數用於創建一個新的Collection這個新的Collection與傳入的Collection有相同的元素後 一個構造函數允許用戶復制一個Collection
如何遍歷Collection中的每一個元素?不論Collection的實際類型如何它都支持一個iterator()的方法該方法返回一個迭代子使用該迭代子即可逐一訪問Collection中每一個元素典型的用法如下
Iterator it = erator(); // 獲得一個迭代子
while(ithasNext()) {
Object obj = itnext(); // 得到下一個元素
}
由Collection接口派生的兩個接口是List和Set
List接口
List是有序的Collection使用此接口能夠精確的控制每個元素插入的位置用戶能夠使用索引(元素在List中的位置類似於數組下標)來訪問List中的元素這類似於Java的數組
和下面要提到的Set不同List允許有相同的元素
除了具有Collection接口必備的iterator()方法外List還提供一個listIterator()方法返回一個 ListIterator接口和標准的Iterator接口相比ListIterator多了一些add()之類的方法允許添加刪除設定元素 還能向前或向後遍歷
實現List接口的常用類有LinkedListArrayListVector和Stack
LinkedList類
LinkedList實現了List接口允許null元素此外LinkedList提供額外的getremoveinsert方法在 LinkedList的首部或尾部這些操作使LinkedList可被用作堆棧(stack)隊列(queue)或雙向隊列(deque)
注意LinkedList沒有同步方法如果多個線程同時訪問一個List則必須自己實現訪問同步一種解決方法是在創建List時構造一個同步的List
List list = CollectionssynchronizedList(new LinkedList());
ArrayList類
ArrayList實現了可變大小的數組它允許所有元素包括nullArrayList沒有同步
sizeisEmptygetset方法運行時間為常數但是add方法開銷為分攤的常數添加n個元素需要O(n)的時間其他的方法運行時間為線性
每個ArrayList實例都有一個容量(Capacity)即用於存儲元素的數組的大小這個容量可隨著不斷添加新元素而自動增加但是增長算法 並沒有定義當需要插入大量元素時在插入前可以調用ensureCapacity方法來增加ArrayList的容量以提高插入效率
和LinkedList一樣ArrayList也是非同步的(unsynchronized)
Vector類
Vector非常類似ArrayList但是Vector是同步的由Vector創建的Iterator雖然和ArrayList創建的 Iterator是同一接口但是因為Vector是同步的當一個Iterator被創建而且正在被使用另一個線程改變了Vector的狀態(例 如添加或刪除了一些元素)這時調用Iterator的方法時將拋出ConcurrentModificationException因此必須捕獲該 異常
Stack 類
Stack繼承自Vector實現一個後進先出的堆棧Stack提供個額外的方法使得Vector得以被當作堆棧使用基本的push和pop 方法還有peek方法得到棧頂的元素empty方法測試堆棧是否為空search方法檢測一個元素在堆棧中的位置Stack剛創建後是空棧
Set接口
Set是一種不包含重復的元素的Collection即任意的兩個元素e和e都有eequals(e)=falseSet最多有一個null元素
很明顯Set的構造函數有一個約束條件傳入的Collection參數不能包含重復的元素
請注意必須小心操作可變對象(Mutable Object)如果一個Set中的可變元素改變了自身狀態導致Objectequals(Object)=true將導致一些問題
Map接口
請注意Map沒有繼承Collection接口Map提供key到value的映射一個Map中不能包含相同的key每個key只能映射一個 valueMap接口提供種集合的視圖Map的內容可以被當作一組key集合一組value集合或者一組keyvalue映射
Hashtable類
Hashtable繼承Map接口實現一個keyvalue映射的哈希表任何非空(nonnull)的對象都可作為key或者value
添加數據使用put(key value)取出數據使用get(key)這兩個基本操作的時間開銷為常數
Hashtable通過initial capacity和load factor兩個參數調整性能通常缺省的load factor 較好地實現了時間和空間的均衡增大load factor可以節省空間但相應的查找時間將增大這會影響像get和put這樣的操作
使用Hashtable的簡單示例如下將放到Hashtable中他們的key分別是onetwothree
Hashtable numbers = new Hashtable();
numbersput(one new Integer());
numbersput(two new Integer());
numbersput(three new Integer());
要取出一個數比如用相應的key
Integer n = (Integer)numbersget(two);
Systemoutprintln(two = + n);
由於作為key的對象將通過計算其散列函數來確定與之對應的value的位置因此任何作為key的對象都必須實現hashCode和equals方 法hashCode和equals方法繼承自根類Object如果你用自定義的類當作key的話要相當小心按照散列函數的定義如果兩個對象相 同即objequals(obj)=true則它們的hashCode必須相同但如果兩個對象不同則它們的hashCode不一定不同如 果兩個不同對象的hashCode相同這種現象稱為沖突沖突會導致操作哈希表的時間開銷增大所以盡量定義好的hashCode()方法能加快哈希 表的操作
如果相同的對象有不同的hashCode對哈希表的操作會出現意想不到的結果(期待的get方法返回null)要避免這種問題只需要牢記一條要同時復寫equals方法和hashCode方法而不要只寫其中一個
Hashtable是同步的
HashMap類
HashMap和Hashtable類似不同之處在於HashMap是非同步的並且允許null即null value和null key但是將HashMap視為Collection時(values()方法可返回Collection)其迭代子操作時間開銷和HashMap 的容量成比例因此如果迭代操作的性能相當重要的話不要將HashMap的初始化容量設得過高或者load factor過低
WeakHashMap類
WeakHashMap是一種改進的HashMap它對key實行弱引用如果一個key不再被外部所引用那麼該key可以被GC回收
總結
如果涉及到堆棧隊列等操作應該考慮用List對於需要快速插入刪除元素應該使用LinkedList如果需要快速隨機訪問元素應該使用ArrayList
如果程序在單線程環境中或者訪問僅僅在一個線程中進行考慮非同步的類其效率較高如果多個線程可能同時操作一個類應該使用同步的類
要特別注意對哈希表的操作作為key的對象要正確復寫equals和hashCode方法
盡量返回接口而非實際的類型如返回List而非ArrayList這樣如果以後需要將ArrayList換成LinkedList時客戶端代碼不用改變這就是針對抽象編程
bcbl
From:http://tw.wingwit.com/Article/program/Java/hx/201311/25679.html