Java Collections Framework

集合 OR 容器

通常我們會用數組去保存一些基本數據類型,數組是編譯器支持的類型,但是數組的一個明顯缺點就是具有固定尺寸,而在一般情況下,只有在程序運行的時候,我們才能知道要保存的具體數目。Java類庫提供了一套相當完善的容器框架(Collections Framework)來解決這個問題。其中基本的類型是List、Set、Queue和Map。這些對象類型也被稱爲集合類,但是由於Java中使用了Collection這個名稱指代該類庫的一個子集,所以一般使用更廣泛的術語“容器”來稱呼它們。

容器的基本任務是保存對象,更準確地說是保存對象的引用。但是各種容器的實現是存在很大差異的,沒有一種容器是絕對優秀地能夠適應所有的應用場景,所以我們需要了解各種容器的底層實現,然後根據實際的情況選擇合適的容器。

從下面的這張容器的分類圖中就能看到Collections Framework的龐大,而且這還不包括Queue接口的實現(PriorityQueue以及各種風格的BlockingQueue等)、ConcurrentMap接口實現、CopyOnWriteArrayList和CopyOnWriteArraySet、EnumSet和EnumMap、以及Collections工具類中的多個工具方法。

Collections

Java集合框架的基本接口/類層次結構:

java.util.Collection [I] 
+--java.util.List [I] 
   +--java.util.ArrayList [C] 
   +--java.util.LinkedList [C] 
   +--java.util.Vector [C] 
      +--java.util.Stack 
+--java.util.Set [I] 
   +--java.util.HashSet [C] 
   +--java.util.SortedSet [I] 
      +--java.util.TreeSet [C] 
java.util.Map 
+--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]:類 

Java2容器類類庫的用途是“保存對象”,它分爲兩類:

  Collection一組獨立的元素,通常這些元素都服從某種規則。List必須保持元素特定的順序,而Set不能有重複元素。

  Map一組成對的“鍵值對”對象,即其元素是成對的對象,最典型的應用就是數據字典,並且還有其它廣泛的應用。另外,Map可以返回其所有鍵組成的Set和其所有值組成的Collection,或其鍵值對組成的Set,並且還可以像數組一樣擴展多維Map,只要讓Map中鍵值對的每個“值”是一個Map即可。

Collection是集合接口
Set子接口:無序,不允許重複。
List子接口:有序,可以有重複元素。
區別:Collections是集合類

同時,List還提供一個listIterator()方法,返回一個ListIterator接口對象,和Iterator接口相比,ListIterator添加了元素的添加,刪除和設定等方法,還能向前或向後遍歷。

Set和List具體子類:
Set
|————HashSet:以哈希表的形式存放元素,插入刪除速度很快。

List
|————ArrayList:動態數組。
|————LinkedList:鏈表、隊列、堆棧。

Vector是一種老的動態數組,是線程同步的,效率很低,一般不贊成使用。


Interface接口規範

Collections Framework定義了一些接口規範,那些常用的容器都會繼承某些接口規範,每一種接口都對應給出相應的抽象類,如果類庫提供的容器不能很好地完成你指定的任務,你可以擴寫這些抽象類的子類,定製自己的容器。

Collection接口

僅僅表示一組對象的集合,而沒有指定對象的存放次序,以及能否包含重複元素,Collection接口自身還繼承了Iterator接口。 下面要說的很多容器都實現了Collection接口,包括List、Set、Queue、Deque等接口。需要注意的是,同爲容器的Map沒有實現Collection接口。 Collection接口定義了容器最基本的一些特性,包含以下的接口方法定義:

size方法:返回容器中元素的個數
contains方法:返回容器中是否包含某個元素
iterator方法:返回容器的迭代器
add方法:用於向容器中添加元素
remove方法:用於刪除容器中的元素
clear方法:清空容器中的元素
toArray方法:將容器類轉成相應的對象數組

List接口

List繼承於Collection接口,表示一個有序容器,容器內的元素會按照加入的順序有序地存放,允許出現重複的元素,可以基於元素位置的訪問。List接口在Collection接口的基礎上加上了以下方法的定義:

get方法:獲取指定位置的元素
set方法:將指定位置設置成指定的元素
indexOf方法:獲取指定元素在容器中的位置
listIterator方法:返回ListIterator類型的迭代器
subList方法:根據區間位置,獲取容器的子容器
List接口的常見實現類有ArrayList、LinkedList、Vector等。

Set接口

繼承於Collection接口,特點是不能存放相同的元素,對有序性沒有要求,Set接口中的方法定義基本和Collection接口一致,沒有加入新的方法定義。
常見的Set接口的實現有HashSet、SortedSet接口

Queue接口

繼承於Collection接口,是一個被定義用來存放一系列等待進行某個過程元素的容器,除了一些基本的容器操作,Queue隊列還提供了一些額外的插入、提取和檢查的操作。
Queue接口中定義以下的方法:

add方法:將指定的元素插入此隊列(如果立即可行且不會違反容量限制),在成功時返回 true,如果當前沒有可用的空間,則拋出 IllegalStateException。
offer方法:將指定的元素插入此隊列(如果立即可行且不會違反容量限制),當使用有容量限制的隊列時,此方法通常要優於 add(E),後者可能無法插入元素,而只是拋出一個異常。
peek方法:獲取但不移除此隊列的頭;如果此隊列爲空,則返回 null。
pool方法:獲取並移除此隊列的頭;如果此隊列爲空,則返回 null。
remove方法:獲取並移除此隊列的頭。
包括Deque、BlockingQueue接口都直接繼承於Queue接口

Map接口

是一個關於key(鍵)和value(值)的映射集合,每一個key對應一個value。
Map接口中定義的一些基本方法:

size方法:返回容器中元素的個數
put方法:向容器中加入元素
remove方法:刪除容器中元素
isEmpty方法:判斷容器是否爲空
contains方法:判斷容器是否包含指定元素
clear方法:清除容器中的元素
keySet方法:返回Map的key集合,是Set類型的
實現了Map接口的一些類:HashMap、Hashtable、WeakHashMap、SynchronizedMap、ConcurrentMap接口等

Deque接口

繼承於Queue接口,在JDK1.6中被加入,也叫做雙端隊列,即可以在隊列的兩端進行插入和提取操作。Deque接口在Queue接口的基礎上,加上了addFirst、addLast、offerFirst、offerLast等方法,分別表示這些操作可以在兩端進行。
常見的Deque的實現類:ArrayDeque、ConcurrentLinkedDeque、LinkedList、BlockingDeque等。

Collections Framework中還包含一些其他的接口,但基本由上述接口擴展而來,如SortedSet、SortedMap、BlockingQueue、BlockingDeque、ConcurrentMap等。


通用的一些實現類

類庫提供了一些非常有用的基於上述接口的容器實現類,並且能夠很好地勝任日常開發中的大部分場景。

HashSet

爲快速查找而設計的Set,存入HashSet的對象必須定義hashCode()。基於Set接口的Hash表的實現,比較全面地實現了Set接口。元素在容器中的順序是無序的,底層是基於HashMap的實現,key表示set容器中的值,value都是一個相同的對象,HashMap的put方法。

TreeSet

保持次序的Set,底層爲樹結構。使用它可以從Set中提取有序的序列。基於紅黑樹實現,繼承於NavigableSet接口,NavigableSet也就是SortedSet的擴展,具有了爲給定搜索目標報告最接近匹配項的導航方法。

LinkedHashSet

具有HashSet的查詢速度,且內部使用鏈表維護元素的順序(插入的次序)。於是在使用迭代器遍歷Set時,結果會按元素插入的次序顯示。

ArrayList

實現了List接口,底層基於數組實現,對元素的隨機訪問速度較快,但是插入和刪除操作速度較慢。ListIterator只應該用來由後或向前遍歷ArrayList,而不是用來插入和刪除元素,因爲這比LinkedList開銷要大很多。

LinkedList

實現了List接口和Deque接口,底層是雙重鏈表實現。當通過隊列使用時,LinkedList表現爲一個FIFO隊列。對順序訪問進行了優化,向LinkedList中間插入與刪除的開銷不大,隨機訪問則相對較慢(可用ArrayList代替)。它具有方法addFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeLast(),這些方法(沒有在任何接口或基類中定義過)使得LinkedList可以當作堆棧、隊列和雙向隊列使用。

ArrayDeque

實現了Deque,是Deque接口一個非常高效的基於數組的實現。

PriorityQueue

是一個基於優先級堆的無界優先級隊列。

HashMap

基於哈希表的 Map 接口的實現。此實現提供所有可選的映射操作,並允許使用 null 值和 null 鍵。(除了不同步和允許使用 null 之外,HashMap 類與 Hashtable 大致相同。)此類不保證映射的順序,特別是它不保證該順序恆久不變。

TreeMap

它實現SortedMap 接口的基於紅黑樹的實現。此類保證了映射按照升序順序排列關鍵字,根據使用的構造方法不同,可能會按照鍵的類的自然順序進行排序(Comparable),或者按照創建時所提供的比較器(Comparator)進行排序。

LinkedHashMap

Map接口的哈希表和鏈表實現,具有可預期的迭代順序。


包裝實現類

在java.util.Collections工具類中提供了一系列的靜態內部類容器,這些內部類也實現了Collection接口,並且具有各自的特性,可以分爲以下三類:

Collections.unmodifiableInterface:返回指定Interface類型的容器,但是不允許用戶去修改它們。相當於原來容器的一個不能修改的視圖。

Collections.synchronizedInterface:返回指定interface類型的容器,但是是線程安全的。

Collections.checkedInterface:返回指定interface的一個動態類型安全視圖。試圖插入一個錯誤類型的元素將導致立即拋出ClassCastException。


基於特定目的的實現

WeakHashMap

我們說容器是用來保存對象的,更準確地說是用來保存對象的引用,如果一個長生命週期的容器,保持着一個無用對象的引用,就會造成GC無法回收。weakHashMap以弱鍵實現的基於哈希表的Map。在 WeakHashMap 中,當某個鍵不再正常使用時,將自動移除其條目。更精確地說,對於一個給定的鍵,其映射的存在並不阻止垃圾回收器對該鍵的丟棄,這就使該鍵成爲可終止的,被終止,然後被回收。丟棄某個鍵時,其條目從映射中有效地移除,因此,該類的行爲與其他的Map實現有所不同。

IdentityHashMap

此類利用哈希表實現Map接口,比較鍵(和值)時使用引用相等性代替對象相等性。換句話說,在 IdentityHashMap 中,當且僅當 (k1==k2) 時,才認爲兩個鍵 k1 和 k2 相等。

CopyOnWriteArrayList

ArrayList的一個線程安全的變體,其中所有可變操作(add、set 等等)都是通過對底層數組進行一次新的複製來實現的,一般需要很大的開銷。

CopyOnWriteArraySet

內部使用CopyOnWriteArrayList的Set。

EnumSet

與枚舉類型一起使用的專用的Set實現。枚舉 set 中所有鍵都必須來自單個枚舉類型,該枚舉類型在創建 set 時顯式或隱式地指定。

EnumMap

與枚舉類型一起使用的專用的Map實現。枚舉映射中所有鍵都必須來自單個枚舉類型,該枚舉類型在創建映射時顯式或隱式地指定。枚舉映射在內部表示爲數組。此表示形式非常緊湊且高效。


線程安全類

下面是線程安全的同步的類:

Vector:就比ArrayList多了個同步化機制(線程安全)。

Statck:堆棧類,先進後出。

Hashtable:就比HashMap多了個線程安全。

Enumeration:枚舉,相當於迭代器。

除了這些之外,其他的都是非線程安全的類和接口。

線程安全的類其方法是同步的,每次只能一個訪問。是重量級對象,效率較低。對於非線程安全的類和接口,在多線程中需要程序員自己處理線程安全問題。


用於併發用的實現類

ConcurrentLinkedQueue

一個基於鏈接節點的無界的線程安全的隊列,按照FIFO原則對元素進行排序。

ConcurrentHashMap

支持獲取的完全併發和更新的所期望可調整併發的哈希表,是基於非阻塞實現的。

LinkedBlockingQueue

一個基於已鏈接節點的、範圍任意的blocking queue,也是按照FIFO排序元素。

PriorityBlockingQueue

一個帶有優先級的阻塞隊列的實現。

其他的併發容器可以在java.util.concurrent包下面找到。


迭代器

迭代器是一種設計模式,它是一個對象,它可以遍歷並選擇序列中的對象,而開發人員不需要了解該序列的底層結構。迭代器通常被稱爲“輕量級”對象,因爲創建它的代價小。

  Java中的Iterator功能比較簡單,並且只能單向移動:

  (1) 使用方法iterator()要求容器返回一個Iterator。第一次調用Iterator的next()方法時,它返回序列的第一個元素。

  (2) 使用next()獲得序列中的下一個元素。

  (3) 使用hasNext()檢查序列中是否還有元素。

  (4) 使用remove()將迭代器新返回的元素刪除。

  Iterator是Java迭代器最簡單的實現,爲List設計的ListIterator具有更多的功能,它可以向前或向後遍歷List,也可以從List中插入、刪除和設定元素。


參考:
http://www.2cto.com/kf/201408/330018.html

發佈了21 篇原創文章 · 獲贊 4 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章