鍍金池/ 教程/ Java/ 集合大家族
Java 集合細(xì)節(jié)(四):保持 compareTo 和 equals 同步
Iterator
使用序列化實現(xiàn)對象的拷貝
fail-fast 機制
關(guān)鍵字 final
Vector
HashTable
Java 集合細(xì)節(jié)(一):請為集合指定初始容量
強制類型轉(zhuǎn)換
數(shù)組之一:認(rèn)識 JAVA 數(shù)組
Java 集合細(xì)節(jié)(三):subList 的缺陷
hashCode
ArrayList
數(shù)組之二
List 總結(jié)
LinkedList
Java 提高篇(九)—–實現(xiàn)多重繼承
Java 的四舍五入
關(guān)鍵字 static
理解 Java 的三大特性之多態(tài)
抽象類與接口
集合大家族
異常(二)
Java 集合細(xì)節(jié)(二):asList 的缺陷
Map 總結(jié)
TreeSet
equals() 方法總結(jié)
Java 提高篇(十)—–詳解匿名內(nèi)部類
HashMap
Stack
詳解內(nèi)部類
TreeMap
異常(一)
詳解 Java 定時任務(wù)
HashSet
字符串
理解 Java 的三大特性之繼承
理解 Java 的三大特性之封裝
代碼塊

集合大家族

在編寫 Java 程序中,我們最常用的除了八種基本數(shù)據(jù)類型,String 對象外還有一個集合類,在我們的的程序中到處充斥著集合類的身影!Java 中集合大家族的成員實在是太豐富了,有常用的 ArrayList、HashMap、HashSet,也有不常用的 Stack、Queue,有線程安全的 Vector、HashTable,也有線程不安全的 LinkedList、TreeMap 等等!

http://wiki.jikexueyuan.com/project/java-enhancement/images/20-1.png" alt="fig.1" />

上面的圖展示了整個集合大家族的成員以及他們之間的關(guān)系。下面就上面的各個接口、基類做一些簡單的介紹(主要介紹各個集合的特點。區(qū)別),更加詳細(xì)的介紹會在不久的將來一一講解。

一、Collection 接口

Collection 接口是最基本的集合接口,它不提供直接的實現(xiàn),Java SDK提供的類都是繼承自 Collection 的“子接口”如 List 和 Set。Collection 所代表的是一種規(guī)則,它所包含的元素都必須遵循一條或者多條規(guī)則。如有些允許重復(fù)而有些則不能重復(fù)、有些必須要按照順序插入而有些則是散列,有些支持排序但是有些則不支持。

在 Java 中所有實現(xiàn)了 Collection 接口的類都必須提供兩套標(biāo)準(zhǔn)的構(gòu)造函數(shù),一個是無參,用于創(chuàng)建一個空的 Collection,一個是帶有 Collection 參數(shù)的有參構(gòu)造函數(shù),用于創(chuàng)建一個新的 Collection,這個新的 Collection 與傳入進(jìn)來的 Collection 具備相同的元素。

二、List 接口

List 接口為 Collection 直接接口。List 所代表的是有序的 Collection,即它用某種特定的插入順序來維護(hù)元素順序。用戶可以對列表中每個元素的插入位置進(jìn)行精確地控制,同時可以根據(jù)元素的整數(shù)索引(在列表中的位置)訪問元素,并搜索列表中的元素。實現(xiàn) List 接口的集合主要有:ArrayList、LinkedList、Vector、Stack。

2.1、ArrayList

ArrayList 是一個動態(tài)數(shù)組,也是我們最常用的集合。它允許任何符合規(guī)則的元素插入甚至包括 null。每一個 ArrayList 都有一個初始容量(10),該容量代表了數(shù)組的大小。隨著容器中的元素不斷增加,容器的大小也會隨著增加。在每次向容器中增加元素的同時都會進(jìn)行容量檢查,當(dāng)快溢出時,就會進(jìn)行擴容操作。所以如果我們明確所插入元素的多少,最好指定一個初始容量值,避免過多的進(jìn)行擴容操作而浪費時間、效率。

size、isEmpty、get、set、iterator 和 listIterator 操作都以固定時間運行。add 操作以分?jǐn)偟墓潭〞r間運行,也就是說,添加 n 個元素需要 O(n) 時間(由于要考慮到擴容,所以這不只是添加元素會帶來分?jǐn)偣潭〞r間開銷那樣簡單)。

ArrayList 擅長于隨機訪問。同時 ArrayList 是非同步的。

2.2、LinkedList

同樣實現(xiàn) List 接口的 LinkedList 與 ArrayList 不同,ArrayList是一個動態(tài)數(shù)組,而 LinkedList 是一個雙向鏈表。所以它除了有 ArrayList 的基本操作方法外還額外提供了 get,remove,insert 方法在 LinkedList 的首部或尾部。

由于實現(xiàn)的方式不同,LinkedList 不能隨機訪問,它所有的操作都是要按照雙重鏈表的需要執(zhí)行。在列表中索引的操作將從開頭或結(jié)尾遍歷列表(從靠近指定索引的一端)。這樣做的好處就是可以通過較低的代價在 List 中進(jìn)行插入和刪除操作。

與 ArrayList 一樣,LinkedList 也是非同步的。如果多個線程同時訪問一個 List,則必須自己實現(xiàn)訪問同步。一種解決方法是在創(chuàng)建 List 時構(gòu)造一個同步的 List:

List list = Collections.synchronizedList(new LinkedList(…));

2.3、Vector

與 ArrayList 相似,但是 Vector 是同步的。所以說 Vector 是線程安全的動態(tài)數(shù)組。它的操作與 ArrayList 幾乎一樣。

2.4、Stack

Stack 繼承自 Vector,實現(xiàn)一個后進(jìn)先出的堆棧。Stack 提供 5 個額外的方法使得 Vector 得以被當(dāng)作堆棧使用?;镜?push 和 pop 方法,還有 peek 方法得到棧頂?shù)脑兀琫mpty 方法測試堆棧是否為空,search 方法檢測一個元素在堆棧中的位置。Stack 剛創(chuàng)建后是空棧。

三、Set 接口

Set 是一種不包括重復(fù)元素的 Collection。它維持它自己的內(nèi)部排序,所以隨機訪問沒有任何意義。與 List 一樣,它同樣運行 null 的存在但是僅有一個。由于 Set 接口的特殊性,所有傳入 Set 集合中的元素都必須不同,同時要注意任何可變對象,如果在對集合中元素進(jìn)行操作時,導(dǎo)致e1.equals(e2)==true,則必定會產(chǎn)生某些問題。實現(xiàn)了 Set 接口的集合有:EnumSet、HashSet、TreeSet。

3.1、EnumSet

是枚舉的專用 Set。所有的元素都是枚舉類型。

3.2、HashSet

HashSet 堪稱查詢速度最快的集合,因為其內(nèi)部是以 HashCode 來實現(xiàn)的。它內(nèi)部元素的順序是由哈希碼來決定的,所以它不保證 set 的迭代順序;特別是它不保證該順序恒久不變。

3.3、TreeSet

基于 TreeMap,生成一個總是處于排序狀態(tài)的 set,內(nèi)部以 TreeMap 來實現(xiàn)。它是使用元素的自然順序?qū)υ剡M(jìn)行排序,或者根據(jù)創(chuàng)建 Set 時提供的 Comparator 進(jìn)行排序,具體取決于使用的構(gòu)造方法。

四、Map 接口

Map 與 List、Set 接口不同,它是由一系列鍵值對組成的集合,提供了 key 到 Value 的映射。同時它也沒有繼承 Collection。在 Map 中它保證了 key 與 value 之間的一一對應(yīng)關(guān)系。也就是說一個 key 對應(yīng)一個 value,所以它不能存在相同的 key 值,當(dāng)然 value 值可以相同。實現(xiàn) map 的有:HashMap、TreeMap、HashTable、Properties、EnumMap。

4.1、HashMap

以哈希表數(shù)據(jù)結(jié)構(gòu)實現(xiàn),查找對象時通過哈希函數(shù)計算其位置,它是為快速查詢而設(shè)計的,其內(nèi)部定義了一個 hash 表數(shù)組(Entry[] table),元素會通過哈希轉(zhuǎn)換函數(shù)將元素的哈希地址轉(zhuǎn)換成數(shù)組中存放的索引,如果有沖突,則使用散列鏈表的形式將所有相同哈希地址的元素串起來,可能通過查看 HashMap.Entry 的源碼它是一個單鏈表結(jié)構(gòu)。

4.2、TreeMap

鍵以某種排序規(guī)則排序,內(nèi)部以 red-black(紅-黑)樹數(shù)據(jù)結(jié)構(gòu)實現(xiàn),實現(xiàn)了 SortedMap 接口

4.3、HashTable

也是以哈希表數(shù)據(jù)結(jié)構(gòu)實現(xiàn)的,解決沖突時與 HashMap 也一樣也是采用了散列鏈表的形式,不過性能比 HashMap 要低

五、Queue

隊列,它主要分為兩大類,一類是阻塞式隊列,隊列滿了以后再插入元素則會拋出異常,主要包括 ArrayBlockQueue、PriorityBlockingQueue、LinkedBlockingQueue。另一種隊列則是雙端隊列,支持在頭、尾兩端插入和移除元素,主要包括:ArrayDeque、LinkedBlockingDeque、LinkedList。

六、異同點

出處:http://blog.csdn.net/softwave/article/details/4166598

6.1、Vector 和 ArrayList

1,vector 是線程同步的,所以它也是線程安全的,而 arraylist 是線程異步的,是不安全的。如果不考慮到線程的安全因素,一般用 arraylist 效率比較高。

2,如果集合中的元素的數(shù)目大于目前集合數(shù)組的長度時,vector 增長率為目前數(shù)組長度的 100%,而 arraylist 增長率為目前數(shù)組長度的 50%.如過在集合中使用數(shù)據(jù)量比較大的數(shù)據(jù),用 vector 有一定的優(yōu)勢。

3,如果查找一個指定位置的數(shù)據(jù),vector 和 arraylist 使用的時間是相同的,都是 0(1),這個時候使用 vector 和 arraylist 都可以。而如果移動一個指定位置的數(shù)據(jù)花費的時間為 0(n-i)n 為總長度,這個時候就應(yīng)該考慮到使用 linklist,因為它移動一個指定位置的數(shù)據(jù)所花費的時間為 0(1),而查詢一個指定位置的數(shù)據(jù)時花費的時間為 0(i)。

ArrayList 和 Vector 是采用數(shù)組方式存儲數(shù)據(jù),此數(shù)組元素數(shù)大于實際存儲的數(shù)據(jù)以便增加和插入元素,都允許直接序號索引元素,但是插入數(shù)據(jù)要設(shè)計到數(shù)組元素移動等內(nèi)存操作,所以索引數(shù)據(jù)快插入數(shù)據(jù)慢,Vector 由于使用了 synchronized 方法(線程安全)所以性能上比 ArrayList 要差,LinkedList 使用雙向鏈表實現(xiàn)存儲,按序號索引數(shù)據(jù)需要進(jìn)行向前或向后遍歷,但是插入數(shù)據(jù)時只需要記錄本項的前后項即可,所以插入數(shù)度較快!

6.2、Aarraylist 和 Linkedlist

1.ArrayList 是實現(xiàn)了基于動態(tài)數(shù)組的數(shù)據(jù)結(jié)構(gòu),LinkedList 基于鏈表的數(shù)據(jù)結(jié)構(gòu)。

2.對于隨機訪問 get 和 set,ArrayList 覺得優(yōu)于 LinkedList,因為 LinkedList 要移動指針。

3.對于新增和刪除操作 add 和 remove,LinedList 比較占優(yōu)勢,因為 ArrayList 要移動數(shù)據(jù)。

這一點要看實際情況的。若只對單條數(shù)據(jù)插入或刪除,ArrayList 的速度反而優(yōu)于 LinkedList。但若是批量隨機的插入刪除數(shù)據(jù),LinkedList 的速度大大優(yōu)于 ArrayList. 因為 ArrayList 每插入一條數(shù)據(jù),要移動插入點及之后的所有數(shù)據(jù)。

6.3、HashMap 與 TreeMap

1、HashMap 通過 hashcode 對其內(nèi)容進(jìn)行快速查找,而 TreeMap 中所有的元素都保持著某種固定的順序,如果你需要得到一個有序的結(jié)果你就應(yīng)該使用 TreeMap(HashMap 中元素的排列順序是不固定的)。HashMap 中元素的排列順序是不固定的)。

2、HashMap 通過 hashcode 對其內(nèi)容進(jìn)行快速查找,而 TreeMap 中所有的元素都保持著某種固定的順序,如果你需要得到一個有序的結(jié)果你就應(yīng)該使用 TreeMap(HashMap 中元素的排列順序是不固定的)。集合框架”提供兩種常規(guī)的 Map 實現(xiàn):HashMap 和 TreeMap (TreeMap 實現(xiàn) SortedMap 接口)。

3、在 Map 中插入、刪除和定位元素,HashMap 是最好的選擇。但如果您要按自然順序或自定義順序遍歷鍵,那么 TreeMap 會更好。使用 HashMap 要求添加的鍵類明確定義了 hashCode() 和 equals() 的實現(xiàn)。 這個 TreeMap 沒有調(diào)優(yōu)選項,因為該樹總處于平衡狀態(tài)。

6.4、hashtable 與 hashmap

1、歷史原因:Hashtable 是基于陳舊的 Dictionary 類的,HashMap 是Java 1.2 引進(jìn)的 Map 接口的一個實現(xiàn) 。

2、同步性:Hashtable 是線程安全的,也就是說是同步的,而 HashMap 是線程序不安全的,不是同步的 。

3、值:只有 HashMap 可以讓你將空值作為一個表的條目的 key 或value。

七、對集合的選擇

7.1、對 List 的選擇

1、對于隨機查詢與迭代遍歷操作,數(shù)組比所有的容器都要快。所以在隨機訪問中一般使用 ArrayList

2、LinkedList 使用雙向鏈表對元素的增加和刪除提供了非常好的支持,而 ArrayList 執(zhí)行增加和刪除元素需要進(jìn)行元素位移。

3、對于 Vector 而已,我們一般都是避免使用。

4、將 ArrayList 當(dāng)做首選,畢竟對于集合元素而已我們都是進(jìn)行遍歷,只有當(dāng)程序的性能因為 List 的頻繁插入和刪除而降低時,再考慮 LinkedList。

7.2、對 Set 的選擇

1、HashSet 由于使用 HashCode 實現(xiàn),所以在某種程度上來說它的性能永遠(yuǎn)比 TreeSet 要好,尤其是進(jìn)行增加和查找操作。

3、雖然 TreeSet 沒有 HashSet 性能好,但是由于它可以維持元素的排序,所以它還是存在用武之地的。

7.3、對 Map 的選擇

1、HashMap 與 HashSet 同樣,支持快速查詢。雖然 HashTable 速度的速度也不慢,但是在 HashMap 面前還是稍微慢了些,所以 HashMap 在查詢方面可以取代 HashTable。

2、由于 TreeMap 需要維持內(nèi)部元素的順序,所以它通常要比 HashMap 和 HashTable 慢。

個人網(wǎng)站:CMSBLOGS