在使用Java的時候,咱們都會遇到使用集合(Collection)的時候,可是Java API提供了多種集合的實現。html
總的說來,Java API中所用的集合類,都是實現了Collection接口,他的一個類繼承結構以下:java
Collection<--List<--Vector
Collection<--List<--ArrayList
Collection<--List<--LinkedList
Collection<--Set<--HashSet
Collection<--Set<--HashSet<--LinkedHashSet
Collection<--Set<--SortedSet<--TreeSet數組
Vector : 基於Array的List,其實就是封裝了Array所不具有的一些功能方便咱們使用,它不可能不受Array的限制。性能也就不可能超越Array。所 以,在可能的狀況下,咱們要多運用Array。另外很重要的一點就是Vector :sychronized」的,這個也是Vector和 ArrayList的惟一的區別。安全
ArrayList:同Vector同樣是一個基於Array上的鏈表,可是不一樣的是ArrayList不是同步的。因此在性能上要比Vector優越一些,可是當運行到多線程環境中時,可須要本身在管理線程的同步問題。數據結構
LinkedList:LinkedList不一樣於前面兩種List,它不是基於Array的,因此不受Array性能的限制。它每個節點(Node)都包含兩方面的內容:1.節點自己的數據(data);2.下一個節點的信息(nextNode)。因此當對LinkedList作添加,刪除動做的時候就不用像基於Array的List同樣,必須進行大量的數據移動。只要更改nextNode的相關信息就能夠實現了。這就是LinkedList的優點。多線程
List總結:異步
1. 全部的List中只能容納單個不一樣類型的對象組成的表,而不是Key-Value鍵值對。例如:[ tom,1,c ];性能
2. 全部的List中能夠有相同的元素,例如Vector中能夠有 [ tom,koo,too,koo ];spa
3. 全部的List中能夠有null元素,例如[ tom,null,1 ];線程
4. 基於Array的List(Vector,ArrayList)適合查詢,而LinkedList(鏈表)適合添加,刪除操做。
HashSet:雖然Set同List都實現了Collection接口,可是他們的實現方式卻大不同。List基本上都是以Array爲基礎。可是Set則是在HashMap的基礎上來實現的,這個就是Set和List的根本區別。HashSet的存儲方式是把HashMap中的Key做爲Set的對應存儲項。看看HashSet的add(Object obj)方法的實現就能夠一目瞭然了。
public boolean add(Object obj)
{
return map.put(obj, PRESENT) == null;
}
這個也是爲何在Set中不能像在List中同樣有重複的項的根本緣由,由於HashMap的key是不能有重複的。
LinkedHashSet:HashSet的一個子類,一個鏈表。
TreeSet:SortedSet的子類,它不一樣於HashSet的根本就是TreeSet是有序的。它是經過SortedMap來實現的。
Set總結:
1. Set實現的基礎是Map(HashMap);
2. Set中的元素是不能重複的,若是使用add(Object obj)方法添加已經存在的對象,則會覆蓋前面的對象
爲何要使用集合類 ?
當你事先不知道要存放數據的個數,或者你須要一種比數組下標存取機制更靈活的方法時,你就須要用到集合類。
理解集合類
集合類存放於java.util包中。
集合類存放的都是對象的引用,而非對象自己,出於表達上的便利,咱們稱集合中的對象就是指集合中對象的引用(reference)。
集合類型主要有3種:set(集)、list(列表)和map(映射)。
(1)集
集(set)是最簡單的一種集合,它的對象不按特定方式排序,只是簡單的把對象加入集合中,就像往口袋裏放東西。
對集中成員的訪問和操做是經過集中對象的引用進行的,因此集中不能有重複對象。
集也有多種變體,能夠實現排序等功能,如TreeSet,它把對象添加到集中的操做將變爲按照某種比較規則將其插入到有序的對象序列中。它實現的是SortedSet接口,也就是加入了對象比較的方法。經過對集中的對象迭代,咱們能夠獲得一個升序的對象集合。
(2)列表
列表的主要特徵是其對象以線性方式存儲,沒有特定順序,只有一個開頭和一個結尾,固然,它與根本沒有順序的集是不一樣的。
列表在數據結構中分別表現爲:數組和向量、鏈表、堆棧、隊列。
關於實現列表的集合類,是咱們平常工做中常常用到的,將在後邊的筆記詳細介紹。
(3)映射
映射與集或列表有明顯區別,映射中每一個項都是成對的。映射中存儲的每一個對象都有一個相關的關鍵字(Key)對象,關鍵字決定了對象在映射中的存儲位置,檢索對象時必須提供相應的關鍵字,就像在字典中查單詞同樣。關鍵字應該是惟一的。
關鍵字自己並不能決定對象的存儲位置,它須要對過一種散列(hashing)技術來處理,產生一個被稱做散列碼(hash code)的整數值,
散列碼一般用做一個偏置量,該偏置量是相對於分配給映射的內存區域起始位置的,由此肯定關鍵字/對象對的存儲位置。理想狀況下,散列處理應該產生給定範圍內均勻分佈的值,並且每一個關鍵字應獲得不一樣的散列碼。
集合類簡介
java.util中共有13個類可用於管理集合對象,它們支持集、列表或映射等集合,如下是這些類的簡單介紹
集:
HashSet: 使用HashMap的一個集的實現。雖然集定義成無序,但必須存在某種方法能至關高效地找到一個對象。使用一個HashMap對象實現集的存儲和檢索操做是在固定時間內實現的.
TreeSet: 在集中以升序對對象排序的集的實現。這意味着從一個TreeSet對象得到第一個迭代器將按升序提供對象。TreeSet類使用了一個TreeMap.
列表:
Vector: 實現一個相似數組同樣的表,自動增長容量來容納你所需的元素。使用下標存儲和檢索對象就象在一個標準的數組中同樣。你也能夠用一個迭代器從一個Vector中檢索對象。Vector是惟一的同步容器類!!當兩個或多個線程同時訪問時也是性能良好的。
Stsck: 這個類從Vector派生而來,而且增長了方法實現棧!一種後進先出的存儲結構。
LinkedList: 實現一個鏈表。由這個類定義的鏈表也能夠像棧或隊列同樣被使用。
ArrayList: 實現一個數組,它的規模可變而且能像鏈表同樣被訪問。它提供的功能相似Vector類但不一樣步。
映射:
HashTable: 實現一個映象,全部的鍵必須非空。爲了能高效的工做,定義鍵的類必須實現hashcode()方法和equal()方法。這個類是前面java實現的一個繼承,而且一般能在實現映象的其餘類中更好的使用。
HashMap: 實現一個映象,容許存儲空對象,並且容許鍵是空(因爲鍵必須是惟一的,固然只能有一個)。
WeakHashMap: 實現這樣一個映象:一般若是一個鍵對一個對象而言再也不被引用,鍵/對象對將被捨棄。這與HashMap造成對照,映象中的鍵維持鍵/對象對的生命週期,儘管使用映象的程序再也不有對鍵的引用,而且所以不能檢索對象。
TreeMap: 實現這樣一個映象,對象是按鍵升序排列的。
Set和List都是由公共接口Collection擴展而來,因此它們均可以使用一個類型爲Collection的變量來引用。這就意味着任何列 表或集構成的集合均可以用這種方式引用,只有映射類除外(但也不是徹底排除在外,由於能夠從映射得到一個列表。)因此說,把一個列表或集傳遞給方法的標準 途徑是使用Collection類型的參數。
Vector 仍是ArrayList,哪個更好,爲何?
要回答這個問題不能一律而論,有時候使用Vector比較好;有時是ArrayList,有時候這兩個都不是最好的選擇。你別期望可以得到一個簡單確定答案,由於這要看你用它們幹什麼。下面有4個要考慮的因素:
(1)API
(2)同步處理
(3)數據增加性
(4)使用模式
下面針對這4個方面進行一一探討
API
在由Ken Arnold等編著的《Java Programming Language》(Addison-Wesley, June 2000)一書中有這樣的描述,Vector相似於ArrayList.。全部從API的角度來看這兩個類很是類似。但他們之間也仍是有一些主要的區別 的。
同步性
Vector是同步的。這個類中的一些方法保證了Vector中的對象是線程安全的。而ArrayList則是異步的,所以ArrayList中的 對象並非線程安全的。由於同步的要求會影響執行的效率,因此若是你不須要線程安全的集合那麼使用ArrayList是一個很好的選擇,這樣能夠避免因爲 同步帶來的沒必要要的性能開銷。
數據增加
從內部實現機制來說ArrayList和Vector都是使用數組(Array)來控制集合中的對象。當你向這兩種類型中增長元素的時候,若是元素 的數目超出了內部數組目前的長度它們都須要擴展內部數組的長度,Vector缺省狀況下自動增加原來一倍的數組長度,ArrayList是原來的50%, 因此最後你得到的這個集合所佔的空間老是比你實際須要的要大。因此若是你要在集合中保存大量的數據那麼使用Vector有一些優點,由於你能夠經過設置集 合的初始化大小來避免沒必要要的資源開銷。
使用模式
在ArrayList和Vector中,從一個指定的位置(經過索引)查找數據或是在集合的末尾增長、移除一個元素所花費的時間是同樣的,這個時間 咱們用O(1)表示。可是,若是在集合的其餘位置增長或移除元素那麼花費的時間會呈線形增加:O(n-i),其中n表明集合中元素的個數,i表明元素增長 或移除元素的索引位置。爲何會這樣呢?覺得在進行上述操做的時候集合中第i和第i個元素以後的全部元素都要執行位移的操做。這一切意味着什麼呢?
這意味着,你只是查找特定位置的元素或只在集合的末端增長、移除元素,那麼使用Vector或ArrayList均可以。若是是其餘操做,你最好選擇其餘的集合操做類。
比 如,LinkList集合類在增長或移除集合中任何位置的元素所花費的時間都是同樣的—O(1),但它在索引一個元素的使用卻比較慢-O(i),其中i是 索引的位置.使用ArrayList也很容易,由於你能夠簡單的使用索引來代替建立iterator對象的操做。LinkList也會爲每一個插入的元素創 建對象,因此你要明白它也會帶來額外的開銷。
最後,在《Practical Java》一書中Peter Haggar建議使用一個簡單的數組(Array)來代替Vector或ArrayList。尤爲是對於執行效率要求高的程序更應如此。由於使用數組 (Array)避免了同步、額外的方法調用和沒必要要的從新分配空間的操做。