1. 程式人生 > >Map、Set、List、Collection、Queue、Stack的特點與用法。

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允許重複。