Java數據結構之集合

前言

Java中集合大家族的成員實在是太豐富了,有常用的ArrayList、HashMap、HashSet,也有不常用的Stack、Queue,有線程安全的Vector、HashTable,也有線程不安全的LinkedList、TreeMap等等。


java集合類

一、Collection接口

Collection接口是最基本的集合接口,它不提供直接的實現,Java SDK提供的類都是繼承自Collection的“子接口”如List和Set。Collection所代表的是一種規則,它所包含的元素都必須遵循一條或者多條規則。如有些允許重復而有些則不能重復、有些必須要按照順序插入而有些則是散列,有些支持排序但是有些則不支持。
????在Java中所有實現了Collection接口的類都必須提供兩套標準的構造函數,一個是無參,用于創建一個空的Collection,一個是帶有Collection參數的有參構造函數,用于創建一個新的Collection,這個新的Collection與傳入進來的Collection具備相同的元素。

二、List接口

List接口為Collection直接接口。List所代表的是有序的Collection,即它用某種特定的插入順序來維護元素順序。用戶可以對列表中每個元素的插入位置進行精確地控制,同時可以根據元素的整數索引(在列表中的位置)訪問元素,并搜索列表中的元素。實現List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。
2.1、ArrayList
????ArrayList是一個動態數組,也是我們最常用的集合。它允許任何符合規則的元素插入甚至包括null。每一個ArrayList都有一個初始容量(10),該容量代表了數組的大小。隨著容器中的元素不斷增加,容器的大小也會隨著增加。在每次向容器中增加元素的同時都會進行容量檢查,當快溢出時,就會進行擴容操作。所以如果我們明確所插入元素的多少,最好指定一個初始容量值,避免過多的進行擴容操作而浪費時間、效率。
????size、isEmpty、get、set、iterator 和 listIterator 操作都以固定時間運行。add 操作以分攤的固定時間運行,也就是說,添加 n 個元素需要 O(n) 時間(由于要考慮到擴容,所以這不只是添加元素會帶來分攤固定時間開銷那樣簡單)。
????ArrayList擅長于隨機訪問。同時ArrayList是非同步的。
2.2、LinkedList
????同樣實現List接口的LinkedList與ArrayList不同,ArrayList是一個動態數組,而LinkedList是一個雙向鏈表。所以它除了有ArrayList的基本操作方法外還額外提供了get,remove,insert方法在LinkedList的首部或尾部。
????由于實現的方式不同,LinkedList不能隨機訪問,它所有的操作都是要按照雙重鏈表的需要執行。在列表中索引的操作將從開頭或結尾遍歷列表(從靠近指定索引的一端)。這樣做的好處就是可以通過較低的代價在List中進行插入和刪除操作。
????與ArrayList一樣,LinkedList也是非同步的。如果多個線程同時訪問一個List,則必須自己實現訪問同步。一種解決方法是在創建List時構造一個同步的List: List list = Collections.synchronizedList(new LinkedList(...));
2.3、Vector
????與ArrayList相似,但是Vector是同步的。所以說Vector是線程安全的動態數組。它的操作與ArrayList幾乎一樣。
2.4、Stack
????Stack繼承自Vector,實現一個后進先出的堆棧。Stack提供5個額外的方法使得Vector得以被當作堆棧使用。基本的push和pop 方法,還有peek方法得到棧頂的元素,empty方法測試堆棧是否為空,search方法檢測一個元素在堆棧中的位置。Stack剛創建后是空棧。

三、Set接口

Set是一種不包括重復元素的Collection。它維持它自己的內部排序,所以隨機訪問沒有任何意義。與List一樣,它同樣運行null的存在但是僅有一個。由于Set接口的特殊性,所有傳入Set集合中的元素都必須不同,同時要注意任何可變對象,如果在對集合中元素進行操作時,導致e1.equals(e2)==true,則必定會產生某些問題。實現了Set接口的集合有:EnumSet、HashSet、TreeSet。
3.1、EnumSet
????是枚舉的專用Set。所有的元素都是枚舉類型。
3.2、HashSet
????HashSet堪稱查詢速度最快的集合,因為其內部是以HashCode來實現的。它內部元素的順序是由哈希碼來決定的,所以它不保證set 的迭代順序;特別是它不保證該順序恒久不變。
3.3、TreeSet
????基于TreeMap,生成一個總是處于排序狀態的set,內部以TreeMap來實現。它是使用元素的自然順序對元素進行排序,或者根據創建Set 時提供的 Comparator 進行排序,具體取決于使用的構造方法。

四、Map接口

Map與List、Set接口不同,它是由一系列鍵值對組成的集合,提供了key到Value的映射。同時它也沒有繼承Collection。在Map中它保證了key與value之間的一一對應關系。也就是說一個key對應一個value,所以它不能存在相同的key值,當然value值可以相同。實現map的有:HashMap、TreeMap、HashTable、Properties、EnumMap。
4.1、HashMap
????以哈希表數據結構實現,查找對象時通過哈希函數計算其位置,它是為快速查詢而設計的,其內部定義了一個hash表數組(Entry[] table),元素會通過哈希轉換函數將元素的哈希地址轉換成數組中存放的索引,如果有沖突,則使用散列鏈表的形式將所有相同哈希地址的元素串起來,可能通過查看HashMap.Entry的源碼它是一個單鏈表結構。
4.2、TreeMap
????鍵以某種排序規則排序,內部以red-black(紅-黑)樹數據結構實現,實現了SortedMap接口
4.3、HashTable
????也是以哈希表數據結構實現的,解決沖突時與HashMap也一樣也是采用了散列鏈表的形式,不過性能比HashMap要低

五、Queue

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

六、異同點

6.1、Vector和ArrayList

  1. vector是線程同步的,所以它也是線程安全的,而arraylist是線程異步的,是不安全的。如果不考慮到線程的安全因素,一般用arraylist效率比較高。
  2. 如果集合中的元素的數目大于目前集合數組的長度時,vector增長率為目前數組長度的100%,而arraylist增長率為目前數組長度的50%.如過在集合中使用數據量比較大的數據,用vector有一定的優勢。
  3. 如果查找一個指定位置的數據,vector和arraylist使用的時間是相同的,都是0(1),這個時候使用vector和arraylist都可以。而如果移動一個指定位置的數據花費的時間為0(n-i)n為總長度,這個時候就應該考慮到使用linklist,因為它移動一個指定位置的數據所花費的時間為0(1),而查詢一個指定位置的數據時花費的時間為0(i)。

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

6.2、Aarraylist和Linkedlist

  1. ArrayList是實現了基于動態數組的數據結構,LinkedList基于鏈表的數據結構。
  2. 對于隨機訪問get和set,ArrayList覺得優于LinkedList,因為LinkedList要移動指針。
  3. 對于新增和刪除操作add和remove,LinedList比較占優勢,因為ArrayList要移動數據。

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

6.3、HashMap與TreeMap

  1. HashMap通過hashcode對其內容進行快速查找,而TreeMap中所有的元素都保持著某種固定的順序,如果你需要得到一個有序的結果你就應該使用TreeMap(HashMap中元素的排列順序是不固定的)。HashMap中元素的排列順序是不固定的)。
  2. HashMap通過hashcode對其內容進行快速查找,而TreeMap中所有的元素都保持著某種固定的順序,如果你需要得到一個有序的結果你就應該使用TreeMap(HashMap中元素的排列順序是不固定的)。集合框架”提供兩種常規的Map實現:HashMap和TreeMap (TreeMap實現SortedMap接口)。
  3. 在Map 中插入、刪除和定位元素,HashMap 是最好的選擇。但如果您要按自然順序或自定義順序遍歷鍵,那么TreeMap會更好。使用HashMap要求添加的鍵類明確定義了hashCode()和 equals()的實現。 這個TreeMap沒有調優選項,因為該樹總處于平衡狀態。

6.4、HashTable與HashMap

  1. 歷史原因:Hashtable是基于陳舊的Dictionary類的,HashMap是Java 1.2引進的Map接口的一個實現 。
  2. 同步性:Hashtable是線程安全的,也就是說是同步的,而HashMap是線程序不安全的,不是同步的 。
  3. 值:只有HashMap可以讓你將空值作為一個表的條目的key或value 。

七、對集合的選擇

7.1、對List的選擇

  1. 對于隨機查詢與迭代遍歷操作,數組比所有的容器都要快。所以在隨機訪問中一般使用ArrayList
  2. LinkedList使用雙向鏈表對元素的增加和刪除提供了非常好的支持,而ArrayList執行增加和刪除元素需要進行元素位移。
  3. 對于Vector而已,我們一般都是避免使用。
  4. 將ArrayList當做首選,畢竟對于集合元素而已我們都是進行遍歷,只有當程序的性能因為List的頻繁插入和刪除而降低時,再考慮LinkedList。

7.2、對Set的選擇

  1. HashSet由于使用HashCode實現,所以在某種程度上來說它的性能永遠比TreeSet要好,尤其是進行增加和查找操作。
  2. 雖然TreeSet沒有HashSet性能好,但是由于它可以維持元素的排序,所以它還是存在用武之地的。

7.3、對Map的選擇

  1. HashMap與HashSet同樣,支持快速查詢。雖然HashTable速度的速度也不慢,但是在HashMap面前還是稍微慢了些,所以HashMap在查詢方面可以取代HashTable。
  2. 由于TreeMap需要維持內部元素的順序,所以它通常要比HashMap和HashTable慢。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,572評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,071評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,409評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,569評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,360評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,895評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,979評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,123評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,643評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,559評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,742評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,250評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,981評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,363評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,622評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,354評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,707評論 2 370

推薦閱讀更多精彩內容

  • Collection ├List │├LinkedList │├ArrayList │└Vector │└Stac...
    AndyZX閱讀 884評論 0 1
  • 概述 Java集合框架由Java類庫的一系列接口、抽象類以及具體實現類組成。我們這里所說的集合就是把一組對象組織到...
    absfree閱讀 1,261評論 0 10
  • Collection接口 Collection接口是所有集合的祖先類。他有兩個構造方法,一個無參構造,一個是帶Co...
    夜幕繁華閱讀 601評論 0 0
  • 集合類簡介 為什么出現集合類?面向對象語言對事物的體現都是以對象的形式,所以為了方便對多個對象的操作,就要對對象進...
    阿敏其人閱讀 1,432評論 0 7
  • 給淳的表白信 淳,我向你介紹一下我自己,馬天助,今天我以一個愛你的人的身份出現在你的面前,對于我,或許你還不了解,...
    天助天豬天珠閱讀 524評論 6 0