1. 程式人生 > >淺析Java中的集合包(ArrayList,LinkedList,Vector, Stack,HashSet,TreeSet,HashMap,TreeMap)

淺析Java中的集合包(ArrayList,LinkedList,Vector, Stack,HashSet,TreeSet,HashMap,TreeMap)

集合包是Java中最常用的包,它最常用的有Collection和Map兩個介面的實現類,Collection用於存放多個單物件,Map用於存放Key-Value形式的鍵值對。

        Collection中常用的又分為兩種型別的介面:List和Set,兩者最明顯的差別為List支援放入重複的物件,而Set不支援。List介面常用的實現類有:ArrayList,LinkedList,Vector和Stack;Set介面常用的實現有HashSet,TreeSet。而Map的常用實現有TreeMap和HashMap。

1. ArrayList基於陣列方式實現,無容量的限制。

2. ArrayList在執行插入元素時可能要擴容,在刪除陣列時並不會減少陣列的容量(如希望相應的減少陣列的容量,可以呼叫ArrayList的trimToSize()),在查詢元素時需要遍歷陣列,對於非null的元素採取equals的方式尋找。

3.ArrayList是非執行緒安全的。

1. LinkedList基於雙向連結串列機制實現。

2. LinkedList在插入元素時,必須建立一個新的Entry物件,並切換相應元素的前後元素的引用;在查詢元素時,須遍歷列表;在刪除元素時,要遍歷列表,找到要刪除的元素,然後從列表上將此元素刪除即可。

3. LinkedList是非執行緒安全的。

從LinkedList和ArrayList的區別來看,我們可容易的得出什麼時候使用ArrayList,什麼時候使用LinkedList:

     1)對於隨機訪問get和set,ArrayList優於LinkedList,因為LinkedList要移動指標。 
     2)  對於新增和刪除操作add和remove,LinedList比較佔優勢,因為ArrayList要移動資料。

三、Vector

      和ArrayList的不同點有

      1) Vector是基於Synchronized實現的執行緒安全的ArrayList。即Vector是執行緒安全的。

      2)在插入元素時容量擴充的機制和ArrayList稍微有所不同,Vector是擴充2倍,並 可通過傳入capacityIncrement來控制容量的擴充。 而ArrayList是擴充1.5倍並加1。

四、Stack

      Stack繼承與Vector,在Vector的基礎上實現了Stack所要求的後進先出(LIFO)的彈出即壓入操作,其提供了push,pop,peek等三個主要方法。

五、HashSet

      1. HashSet基於HashMap實現,無容量限制。

      2. HashSet是非執行緒安全的。 

      3. HashSet不保證有序。

六、TreeSet

      1、TreeSet基於TreeMap實現,支援排序。

      2、TreeSet是非執行緒安全的。

從對HashSet和TreeSet的描述來看,TreeSet和HashSet一樣,也是完全基於Map來實現的,並且都不支援get(int)來獲取指定位置的元素(需要遍歷獲取),另外TreeSet還提供了一些排序方面的支援。例如傳入Comparator實現、descendingSet以及descendingIterator等。 

七、HashMap

       1、HashMap採用陣列方式儲存key,value構成的Entry物件,無容量限制。

       2、HashMap基於Key hash查詢Entry物件存放到陣列的位置,對於hash衝突採用連結串列的方式來解決。

       3、HashMap在插入元素時可能會要擴大陣列的容量,在擴大容量時須要重新計算hash,並複製物件到新的陣列中。

       4、HashMap是非執行緒安全的。

       5、HashMap遍歷使用的是Iterator

八、HashTable

      1、HashTable是執行緒安全的。

      2、HashTable中無論是Key,還是Value都不允許為null。

      3.   HashTable遍歷使用的是Enumeration。

曾經HashTable的應用非常廣泛,HashMap是新框架中用來代替HashTable的類,也就是說建議使用HashMap,不要使用HashTable,可以使用ConcurrentHashMap。那麼幾者之間有什麼區別呢?

      1、HashTable的內部儲存結構

HashTable和HashMap採用相同的儲存機制,二者的實現基本一致,不同的是:

     1)、HashMap是非執行緒安全的,HashTable是執行緒安全的,內部的方法基本都是synchronized。

     2)、HashTable不允許有null值的存在。

在HashTable中呼叫put方法時,如果key為null,直接丟擲NullPointerException。其它細微的差別還有,比如初始化Entry陣列的大小等等,但基本思想和HashMap一樣。

       2、HashTable和 ConcurrentHashMap的比較

ConcurrentHashMap是目前最好的執行緒安全的HashMap的實現。同樣是執行緒安全的類,它與HashTable在同步方面有什麼不同呢?

HashTable使用synchronized關鍵字來確保同步,而Synchronized其實是對物件加鎖,不論你是在方法前加synchronized還是語句塊前加, 鎖住的都是物件整體 , 但是ConcurrentHashMap的同步機制和這個不同,它不是加synchronized關鍵字,而是基於lock操作的,這樣的目的是保證同步的時候,鎖住的不是整個物件。事實上,ConcurrentHashMap可以滿足concurrentLevel個執行緒併發無阻塞的操作集合物件。

需要特別注意的是,我們在具體的專案開發中必須對HashMap的非執行緒安全保持足夠的關注,如果在併發場景中不保持足夠的同步,就有可能在執行HashMap.get是進入死迴圈,將CPU耗到100%。

       1、TreeMap是一個典型的基於紅黑樹的Map實現,因此它要求一定要有Key比較的方法,要麼傳入Comparator實現,要麼key物件實現Comparable介面。

       2、TreeMap是非執行緒安全的。