Map、Set、List、Collection、Queue、Stack的特點與用法。
java集合框架的基本介面/類層次結構
java.util.Collection [I] +--java.util.List [I] +--java.util.ArrayList [C] +--java.util.LinkedList [C] +--java.util.Vector [C] +--java.util.Stack [C] +--java.util.Set [I] +--java.util.HashSet [C] +--java.util.SortedSet [I] +--java.util.TreeSet [C] java.util.Map [I]+--java.util.SortedMap [I] +--java.util.TreeMap [C] +--java.util.Hashtable [C] +--java.util.HashMap [C] +--java.util.LinkedHashMap [C] +--java.util.WeakHashMap [C] [I]:介面 [C]:類
那麼,為什麼要有集合類?
面向物件的語言對事物的體現都是以物件的形式,為了方便對多個物件操作,就要對物件進行儲存,集合類就是對多個物件進行儲存的一種方式。
陣列和集合類有何不同?
最主要的區別是長度可變不可變問題。陣列可以儲存物件,但是長度是固定的,不可變的。集合長度是可變的。其次,陣列中可以儲存基本資料型別,集合只能儲存物件。集合的一個比較大的優點是可以儲存不同型別的物件。陣列不可以。
下面就開始各種總結。
Collection介面
Collection介面是最基本的集合介面,代表一組Object集合,這些Object被稱作Collection的元素,所有實現Collection介面的型別必須提供兩個標準的建構函式:無引數的建構函式用於建立一個空的Collection,有一個Collection引數的建構函式用於建立一個新的Collection,這個新的Collection與傳入的Collection有相同的元素後一個建構函式允許使用者複製一個Collection。這些都比較容易理解。
1 Collection<Integer> ci = new ArrayList<Integer>();2 Collection<Integer> ci2 = new ArrayList<Integer>(Arrays.asList(1,2,3,4,5));
並且注意Collection中沒有get()方法,要想檢視或者操作Collection中的元素只能遍歷,使用的是iterator()方法,使用該方法可以逐一訪問Collection的每一個元素。
1 Iterator it = collection.iterator();//獲得迭代 2 while(it.hasNext()){ 3 Object obj = it.next();//得到下一個元素 4 }
由上圖可知,Collection分為Lst介面和Set介面。
List介面
List介面是有序的Collection,使用該介面能精確控制每個元素的插入位置,可以使用索引來訪問List中的元素,跟陣列是很類似的。並且List中允許有重複元素,當然有些List的實現類不允許重複元素的存在。
List中有iterator()方法,還有listIterator方法,返回一個ListIterator介面,這個介面比標準的Iterator介面相比,多了一些add之類的方法,允許新增、刪除、設定元素值以及向前或者向後遍歷等。
如上圖,List下有幾個常用類:LinkedList、ArrayList和Vector以及Stack。
(1)ArrayList類:實現了可變大小的陣列。它允許包含所有元素,包括null。每個ArrayList例項都有一個容量,即用於儲存元素的陣列的大小,這個容量可以隨著不斷新增新元素而自動增加,但增長演算法沒有定義,當插入大量元素時,插入前可以呼叫ensureCapacity方法來增加ArrayList的容量以提高插入效率。
(2)LinkedList類:允許null元素,提供額外的get,remove和insert方法,這使得LinkedList可以用作stack、queue或雙向佇列。它可以再List的中間插入和移除,在這方面比ArrayList有效,但是在隨機訪問方面就沒有ArrayList有效了。如果多個執行緒同時訪問一個List,則必須自己實現訪問同步,一種解決方法是在建立List時構造一個同步的List:
List list = Collection.synchronizedList(new LinkedList(……));
(3)Vector類:Vector跟ArrayList非常類似,但是Vector是同步的,由Vector建立的Iterator,雖然和ArrayList建立的 Iterator是同一介面,但是,因為Vector是同步的,當一個Iterator被建立而且正在被使用,另一個執行緒改變了Vector的狀態(例如,新增或刪除了一些元素),這時呼叫Iterator的方法時將丟擲ConcurrentModificationException,因此必須捕獲該異常。
(4)Stack類:繼承自Vector,實現一個後進先出的棧。提供了幾個基本方法,push、pop、peak、empty、search等。
總結:
- List:元素是有序的,元素可以重複。因為該集合體繫有索引。
-
- ArrayList:底層的資料結構使用的是資料結構。
-
- 查詢速度很快。
- 增刪稍慢。
- 執行緒不同步。
- 預設長度為10增長率為50%。
- LinkedList:底層使用的連結串列資料結構。
-
- 增刪速度很快。
- 查詢稍慢。
- Vector:底層是陣列資料結構。1.0出現
-
- 執行緒同步
- 被ArrayList替代了。
- 長度增長率100%。
Set介面
Set介面是繼承自Collection的,它不能包含有重複元素。Set中最多有一個null元素。
因為Set的這個制約,在使用Set集合的時候,應該注意: 1,為Set集合裡的元素的實現類實現一個有效的equals(Object)方法。 2,對Set的建構函式,傳入的Collection引數不能包含重複的元素。 Set下有幾個set類,HashSet、SortedSet、TreeSet,用的較多的是HashSet,其他兩種基本不常用,以後慢慢補充該方面知識,下面說HashSet。 (1)HashSet,底層資料結構式雜湊表,由雜湊表支援,不保證集合的迭代順序,特別是不保證該順序恆久不變,此類允許使用null元素。HashSet保證元素唯一性的方法是通過元素的兩個方法,hashCode和equals來完成。如果元素的HashCode值相同,才會判斷equals是否為true。如果元素的hashCode值不同,不會呼叫equals。 (2)TreeSet:底層資料結構式二叉樹。注:新增元素必須實現Comparable介面或在例項TreeSet時指定比較器。可以對Set集合中的元素進行排序。保證元素唯一性的依據:compareTo方法return 0; Map介面 Map整合Collection介面,Map和Collection是兩種不同的集合,Collection是值(value)的集合,Map是鍵值對(key,value)的集合。包含幾種主要類和介面:HashMap、LinkedMap、WeakHashMap、SortedMap、TreeMap、HashTable等幾種。 (1)Hashtable繼承Map介面,實現一個key-value對映的雜湊表。任何非空(non-null)的物件都可作為key或者value。新增資料使用put(key, value),取出資料使用get(key),這兩個基本操作的時間開銷為常數。 (2)WeakHashMap類,WeakHashMap是一種改進的HashMap,它對key實行“弱引用”,如果一個key不再被外部所引用,那麼該key可以被GC回收。 總結: 如果涉及到堆疊,佇列等操作,應該考慮用List,對於需要快速插入,刪除元素,應該使用LinkedList,如果需要快速隨機訪問元素,應該使用ArrayList。 如果程式在單執行緒環境中,或者訪問僅僅在一個執行緒中進行,考慮非同步的類,其效率較高,如果多個執行緒可能同時操作一個類,應該使用同步的類。 在除需要排序時使用TreeSet,TreeMap外,都應使用HashSet,HashMap,因為他們 的效率更高。 要特別注意對雜湊表的操作,作為key的物件要正確複寫equals和hashCode方法。 容器類僅能持有物件引用(指向物件的指標),而不是將物件資訊copy一份至數列某位置。一旦將物件置入容器內,便損失了該物件的型別資訊。 儘量返回介面而非實際的型別,如返回List而非ArrayList,這樣如果以後需要將ArrayList換成LinkedList時,客戶端程式碼不用改變。這就是針對抽象程式設計。 注意: 1、Collection沒有get()方法來取得某個元素。只能通過iterator()遍歷元素。 2、Set和Collection擁有一模一樣的介面。 3、List,可以通過get()方法來一次取出一個元素。使用數字來選擇一堆物件中的一個,get(0)...。(add/get) 4、一般使用ArrayList。用LinkedList構造堆疊stack、佇列queue。 5、Map用 put(k,v) / get(k),還可以使用containsKey()/containsValue()來檢查其中是否含有某個key/value。 HashMap會利用物件的hashCode來快速找到key。 6、Map中元素,可以將key序列、value序列單獨抽取出來。 使用keySet()抽取key序列,將map中的所有keys生成一個Set。 使用values()抽取value序列,將map中的所有values生成一個Collection。 為什麼一個生成Set,一個生成Collection?那是因為,key總是獨一無二的,value允許重複。