JAVA基礎整理-集合篇(一),java基礎整理集合
集合作為JAVA的基礎知識,本來感覺自己理解的很清楚了,但是在最近的一次面試中還是答得不盡如人意!再次做一下整理,以便加深理解以及隨時查閱。
首先,java.util包中三個重要的介面及特點:List(列表)、Set(保證集合中元素唯一)、Map(維護多個key-value索引值對,保證key唯一)。
集合架構體系如所示:
圖1
各個集合類型的區別與聯絡如:
介面 |
簡述 |
實現 |
操作特性 |
成員要求 |
Set |
成員不能重複 |
HashSet |
外部無序地遍曆成員 |
成員可為任意Object子類的對象,但如果覆蓋了equals方法,同時注意修改hashCode方法。 |
TreeSet |
外部有序地遍曆成員;附加實現了SortedSet, 支援子集等要求順序的操作 |
成員要求實現caparable介面,或者使用 Comparator構造TreeSet。成員一般為同一類型。 |
LinkedHashSet |
外部按成員的插入順序遍曆成員 |
成員與HashSet成員類似 |
List |
提供基於索引的對成員的隨機訪問 |
ArrayList |
提供快速的基於索引的成員訪問,對尾部成員的增加和刪除支援較好 |
成員可為任意Object子類的對象 |
LinkedList |
對列表中任何位置的成員的增加和刪除支援較好,但對基於索引的成員訪問支援效能較差 |
成員可為任意Object子類的對象 |
Map |
儲存索引值對成員,基於鍵找值操作,compareTo或compare方法對鍵排序 |
HashMap |
能滿足使用者對Map的通用需求 |
鍵成員可為任意Object子類的對象,但如果覆蓋了equals方法,同時注意修改hashCode方法。 |
TreeMap |
支援對鍵有序地遍曆,使用時建議先用HashMap增加和刪除成員,最後從HashMap產生TreeMap;附加實現了SortedMap介面,支援子Map等要求順序的操作 |
鍵成員要求實現caparable介面,或者使用Comparator構造TreeMap。鍵成員一般為同一類型。 |
LinkedHashMap |
保留鍵的插入順序,用equals 方法檢查鍵和值的相等性 |
成員可為任意Object子類的對象,但如果覆蓋了equals方法,同時注意修改hashCode方法。 |
IdentityHashMap |
使用== 來檢查鍵和值的相等性。 |
成員使用的是嚴格相等 |
WeakHashMap |
其行為依賴於記憶體回收線程,沒有絕對理由則少用 |
|
圖2
主要集合介面詳解
Collection 介面
用於表示任何對象或元素組。想要儘可能以常規方式處理一組元素時,就使用這一介面。由Collection介面派生的兩個介面是List和Set
List介面
Java中的List是對數組的有效擴充,它是這樣一種結構,如果不使用泛型,它可以容納任何類型的元素,如果使用泛型,那麼它只能容納泛型指定的類型的元素。和數組相比,List的容量是可以動態擴充的。
List中的元素是可以重複的,裡面的元素是“有序”的,這裡的“有序”,並不是排序的意思,而是說我們可以對某個元素在集合中的位置進行指定。
List中常用的集合對象包括:ArrayList、Vector和LinkedList,其中前兩者是基於數組來進行儲存,後者是基於鏈表進行儲存。其中Vector是安全執行緒的,其餘兩個不是安全執行緒的。
List中是可以包括null的,即使是使用了泛型。
LinkedList類
LinkedList實現了List介面,允許null元素。此外LinkedList提供額外的get,remove,insert方法在 LinkedList的首部或尾部。這些操作使LinkedList可被用作堆棧(stack),隊列(queue)或雙向隊列(deque)。
ArrayList類
ArrayList實現了可變大小的數組。它允許所有元素,包括null。ArrayList沒有同步。
size,isEmpty,get,set方法已耗用時間為常數。但是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提供5個額外的方法使得Vector得以被當作堆棧使用。基本的push和pop 方法,還有peek方法得到棧頂的元素,empty方法測試堆棧是否為空白,search方法檢測一個元素在堆棧中的位置。Stack剛建立後是空棧。
Set介面
Set 介面繼承 Collection 介面,而且它不允許集合中存在重複項,每個具體的 Set 實作類別依賴添加的對象的 equals()方法來檢查獨一性。Set介面沒有引入新方法,所以Set就是一個Collection,只不過其行為不同。
Set可以大致分為兩類:不排序Set和排序Set,不排序Set包括HashSet和LinkedHashSet,排序Set主要指TreeSet。其中HashSet和LinkedHashSet可以包含null。
Hash表
Hash表是一種資料結構,用來尋找對象。Hash表為每個對象計算出一個整數,稱為Hash Code(雜湊碼)。Hash表是個連結式列表的陣列。每個列表稱為一個buckets(雜湊表元)。對象位置的計算 index = HashCode % buckets (HashCode為對象雜湊碼,buckets為雜湊表元總數)。
當你添加元素時,有時你會遇到已經填充了元素的雜湊表元,這種情況稱為Hash Collisions(雜湊衝突)。這時,你必須判斷該元素是否已經存在於該雜湊表中。
如果雜湊碼是合理地隨機分布的,並且雜湊表元的數量足夠大,那麼雜湊衝突的數量就會減少。同時,你也可以通過設定一個初始的雜湊表元數量來更好地控制哈 希表的運行。初始雜湊表元的數量為 buckets = size * 150% + 1 (size為預期元素的數量)。
如果雜湊 表中的元素放得太滿,就必須進行rehashing(再雜湊)。再雜湊使雜湊表元數增倍,並將原有的對象重新匯入新的雜湊表元中,而原始的雜湊表元被刪 除。load factor(載入因子)決定何時要對雜湊表進行再雜湊。在Java程式設計語言中,載入因子預設值為0.75,預設雜湊表元為101。
HashSet類
在更多情況下,優先使用 HashSet 儲存重複自由的集合。考慮到效率,添加到 HashSet 的對象需要採用恰當分配雜湊碼的方式來實現hashCode()方法。雖然大多數系統類別覆蓋了 Object中預設的hashCode()和equals()實現,但建立您自己的要添加到HashSet的類時,別忘了覆蓋 hashCode()和equals()。
TreeSet類
TreeSet是支援排序的一種Set,它的父介面是SortedSet。所以,當您要從集合中以有序的方式插入和抽取元素時,TreeSet實現會有用處。
Map介面
Map介面不是Collection介面的繼承。Map介面用於維護鍵/值對(key/value pairs)。該介面描述了從不重複的鍵到值的映射,和Set類似,Java中的Map也有兩種:排序的和不排序的,不排序的包括HashMap、Hashtable和LinkedHashMap,排序的包括TreeMap。
HashMap類
在Map 中插入、刪除和定位元素,HashMap 是最好的選擇。HashMap不是安全執行緒的,Hashtable是安全執行緒的,我們可以把HashMap看做是“簡化”版的Hashtable
無論HashMap還是Hashtable,我們觀察它的建構函式,就會發現它可以有兩個參數:initialCapacity和loadFactor,預設情況下,initialCapacity等於16,loadFactor等於0.75。這和Hash表中可以存放的元素數目有關係,當元素數目超過initialCapacity*loadFactor時,會觸發rehash方法,對hash表進行擴容。如果我們需要向其中插入過多元素,需要適當調整這兩個參數。
TreeMap類
但如果您要按自然順序或自訂順序遍曆鍵,那麼TreeMap會更好,它不是安全執行緒的。使用HashMap要求添加的鍵類明確定義了hashCode()和 equals()的實現。這個TreeMap沒有調優選項,因為該樹總處於平衡狀態。
LinkedHashMap類
LinkedHashMap擴充HashMap,以插入順序將關鍵字/值對添加進連結雜湊映像中。象LinkedHashSet一樣,LinkedHashMap內部也採用雙重連結式列表。
WeakHashMap類
WeakHashMap是Map的一個特殊實現,它使用WeakReference(弱引用)來存放雜湊表關鍵字。使用這種方式時,當映射的鍵在 WeakHashMap 的外部不再被引用時,垃圾收集器會將它回收,但它將把到達該對象的弱引用納入一個隊列。WeakHashMap的運行將定期檢查該隊列,以便找出新到達的 弱應用。當一個弱引用到達該隊列時,就表示關鍵字不再被任何人使用,並且它已經被收集起來。然後WeakHashMap便刪除相關的映射。
IdentityHashMap類
IdentityHashMap也是Map的一個特殊實現。在這個類中,關鍵字的雜湊碼不應該由hashCode()方法來計算,而應該由 System.identityHashCode方法進行計算(即使已經重新定義了hashCode方法)。這是Object.hashCode根據對象 的記憶體位址來計算雜湊碼時使用的方法。另外,為了對各個對象進行比較,IdentityHashMap將使用==,而不使用equals方法。
換句話說,不同的關鍵字對象,即使它們的內容相同,也被視為不同的對象。IdentityHashMap類可以用於實現對象拓撲結構轉換 (topology-preserving object graph transformations)(比如實現對象的序列化或深度拷貝),在進行轉換時,需要一個“節點表”跟蹤那些已經處理過的對象的引用。即使碰巧有對 象相等,“節點表”也不應視其相等。另一個應用是維護代理對象。比如,調試工具希望在程式調試期間維護每個對象的一個代理對象。
“IdentityHashMap類不是一般意義的Map實現!它的實現有意的違背了Map介面要求通過equals方法比較對象的約定。這個類僅使用在很少發生的需要強調等同性語義的情況。”
參考文章:
http://jianshi-dlw.iteye.com/blog/1179834
http://blog.csdn.net/zhangerqing/article/details/8122075
http://www.cnblogs.com/wing011203/archive/2013/05/07/3066021.html