Java集合相關

在Java開發中,會經常使用到集合,那么何為集合呢?

集合是用于存儲批量數據的容器工具,可以將其看做一個可變長度的數組。

在Java的API中集合被包含在java.util包中,被稱作collection框架。

Collection

我們先從Collection接口說起,接口Collection是collection層次結構的根接口,表示一組對象,一些collection是允許重復,一些則不可以。一些是有序的,而一些則是無序的。

所有通用的Collection實現類(通常通過它的一個子接口間接實現Collection)應該提供兩個“標準”構造方法:一個是 void(無參數)構造方法,用于創建空 collection;另一個是帶有Collection類型單參數的構造方法,用于創建一個具有與其參數相同元素新的 collection。實際上,后者允許用戶復制任何 collection,以生成所需實現類型的一個等效 collection。盡管無法強制執行此約定(因為接口不能包含構造方法),但是 Java 平臺庫中所有通用的Collection實現都遵從它。——官網介紹

下圖是常用Collection集合的簡化UML類圖:

圖一 Collection

Set接口

Set類型的集合存儲的元素是無序的且不可重復。

HashSet

對于HashSet,是基于HashMap(我們將會在后面介紹)實現的。HashSet底層采用HashMap來保存所有元素。主要用來做高性能的集運算,為快速查找而設計。存入HashSet的對象必須重寫hashCode()方法。

當我們向HashSet集合添加元素時,它是按照hash算法來存儲集合中的元素。首先HashSet會調用該對象的hashCode()方法來獲取到該對象的hashCode值,然后根據hashCode值決定該對象在Set集合中的存儲位置。HashSet集合判斷兩個元素相等的標準是兩個對象通過equals方法比較相等,同時兩個元素的hashCode()方法返回值也相等。因此如果兩個元素通過equals方法比較返回為true,但它們通過hashCode()方法返回的值的比較不相等,那么HashSet會將這兩個元素存儲在不同的位置,仍然能夠添加成功。

TreeSet

TreeSet是一種可指定排序方式的Set集合。其底層數據結構是二叉樹。通過比較兩元素的結果是否為0來保證元素的唯一性。

對于TreeSet的指定排序方式的方法有兩種:

方式一:讓元素自身具備比較性。只要讓元素實現Comparable接口,并覆蓋compareTo方法即可,當compareT方法的返回值為0時,就是相同元素。

方式二:讓集合自身具備比較性。該方式通過自定義比較器來實現,自定義類實現Comparator接口,覆蓋compare方法,將該Comparator接口實現類的對象作為參數傳遞給TreeSet的構造方法即可。


List接口

List類型的集合存儲的元素時有序且可重復。

ArrayList

ArrayList底層采用一個可變長度的數組實現,可存儲所有的元素,包括null。由于其實現了Serializable接口,所以其支持序列化。又由于其實現了RandomAccess接口,所以支持快速隨機訪問。ArrayList集合存儲的元素按照存入的先后順序排列元素,也就是說先進先出。

每個ArrayList實例都有一個容量,即用于存儲元素的數組的大小,這個容量可隨著不斷添加新元素而自動增加,。但是增長算法并沒有定義。當需要插入大量元素的時候,再插入前可以調用ensureCapacity方法來增加ArrayList的容量以提高插入效率。

ArrayList歲支持快速隨機訪問,但向集合中插入與移除元素的操作速度很慢。

LinkedList

LinkList在的底層是一個鏈表結構,因此LinkList對于集合增刪操作來說會更加占有優勢,只需要對指針(注:在Java中沒有指針的概念,這里是可以更形象地進行說明)操作即可。又因為鏈表的結構,LinkList可以被用作堆棧,隊列或雙向隊列。

Vector

Vector同ArrayList一樣底層是一個可變長度的數組。(下文有詳細的介紹)

Stack

Stack集合繼承于Vector類,Stack底層是一個堆棧結構,遵循后進先出(LIFO)原則,只能在一端執行插入操作(稱為入棧)或刪除操作(稱為出棧)

peek()//查看棧頂元素 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pop()//出棧,從棧頂移除一個元素 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? push(E Object)//入棧,將一個Object壓入棧頂 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? search(E Object)//查詢某個元素在棧中的位置


下圖是常用Map集合簡化的UML類圖


圖二 Map

Map接口

Map類型的集合以鍵值對的形式存儲數據。不允許鍵的重復和從鍵到值的一對多映射。

HashMap

在HashMao內部通過一個哈希表來管理所有元素,同上文敘述的HashSet類似(其實應該說HashSet同HashMap類似),通過hashCode()方法和equals()方法來保證鍵的唯一性。也因此HashMap通過鍵的hashCode來快速的存取元素。

LinkedHashMap

LinkedHashMap繼承于HashMap,在底層是以哈希表和鏈接列表相結合而實現的.該集合類型保留插入順序,如果需要輸入順序與輸出順序相同,可以采用此集合。在LinkedHashMap內部有兩種排序方式,一種是插入順序(默認),一種是訪問順序(即近期訪問最少到近期訪問最多的順序),這兩種方式通過一個布爾值accessOrder進行切換,在LinkedHashMap的構造方法publicLinkedHashMap(intinitialCapacity,floatloadFactor,booleanaccessOrder)?{ ??super(initialCapacity,?loadFactor); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??this.accessOrder?=?accessOrder;}?中,如果accessOrder為true,表示按照訪問順序存儲元素,如果為false表示按照插入順序訪問元素。

Hashtable

同樣HashMap在底層是通過一個哈希表來實現的。

Properties

Properties繼承于Hashtable,該類表示一個持久的屬性值,可保存在流中或從流中加載。屬性列表中每個鍵及其對應值都是一個字符串。該類主要用于讀取Java中的配置文件,在Java中,其配置文件常為.properties文件,格式為文本文件,文件的內容的格式是“鍵=值”的格式,文本注釋信息可以用"#"來注釋。了解Properties的詳細用法,點我。

TreeMap

TreeMap實現了SortedMap接口,該集合根據鍵的自然順序進行排序,或根據創建集合時傳入的Comparator進行排序,具體取決于使用的構造方法。

各種集合的比較

1.同步性

以上介紹的集合中,除Vector、Stack、HashTable和Properties外,其他集合類型(HashSet、TreeSet、ArrayList、LinkedList、LinkedHashMap、TreeMap)都是非線程安全的。那么當多個線程同時訪問這些非線程的集合類型時,我們必須自己實現訪問同步,一種解決方案是在構造這些集合時構造一個同步集合,通過Collections類的靜態方法synchronizedCollection() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?synchronizedList() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?synchronizedMap() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?synchronizedSet() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?synchronizedSortedMap() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?synchronizedSortedSet()

2.ArrayList與Vector的比較

同步性方面,如1所述,Vector不需要自己實現同步方案,而ArrayList需要自己實現同步方案。ArrayList和Vector都是使用可變長數組來保存數據,當數組空間不足時,兩者就需要擴展其大小,ArrayList增加50%的大小,而Vector在默認情況下增長一倍的大小,但Vector可以自己設定這個增長幅度,在這方面Vector確實是有優勢的,根據情況設定增長幅度,對程序的性能來說會更加友好。

3.LinkedList與ArrayList、Vector的比較

這三種集合類型都支持快速隨機訪問,在集合的首或末對元素進行更重操作,三者并沒有什么的區別,但當從其他任意位置對元素進行操作,在性能上就會產生很大的差異。上文有敘述到LinkList是一個鏈表結構,在任意位置的對元素的操作都在一個常數級的時間,而Arrayl與Vecotr卻頗為費時。

4.HashMap和Hashtable的區別

Hashtable與HashMap類似,但Hashtable不允許鍵與值為null,HashMap卻允許。Hashtable是線程安全的,HashMap是縣城非安全的。相比較下,HashMap比Hashtable效率要高下,所以要根據具體情況選擇使用。。

5.TreeMap和HashMap的比較

針對于TreeMap,HashMap使用起來性能更好,因為在HashMap的構造方法中,可以自己調優初始容量和負載因子,這樣我們就可以根據具體的開發環境去優化我們的HashMap。TreeMap可以自定義順序遍歷元素,這更是與使用在需要具體排序的情況下。但是TreeMap的性能不是很好,TreeMap的get操作的時間復雜度是O(log(n)),針對于HashMap的O(1)差的還是比較多的。因此為了中和兩者,出現了LinkedHashMap。

6.各集合的性能比較

單線程模式下,測試元素在100~1000的情況下:

添加? HashMap效率最高,ArrayList最低,其他的效高的還有Stack、HashSet和Vector,較低的有LinkedList和TreeSet和TreeMap

刪除 HashMap效率最高,LinkedList最低,其他的HashSet、TreeMap和TreeSet效率較高,較低的有Vector、ArrayList和Stack

查找? HashMap效率最高,LinkedList最低,HashXXX和TreeXXX效率都比較高,而基于List類效率耗時是Map或Set的十倍左右。

多線程模式下,測試元素100~1000,線程數10的情況下:

添加 HashSet效率最高,LinkedList最低,HashXXX和TreeXXX效率都比較高,這里ArrayList效率較低,整體相差不大。

刪除 HashSet效率最高,LinkedList最低,整體性能同添加相似,但HashXXX或TreeXXX性能比List系列高出3倍。

查找 仍然是HashSet性能最好,LinkedList最低,性能較差的是ArrayList,其他的均表現很好。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ——摘自Adroid中文網

請根據具體情況具體選擇。

7.移動開發給出的建議

在谷歌官方推出的Android性能優化典范系列視頻中提到,Android為移動操作系統特意編寫了一些更加高效的容器,其中包括SparseArray和ArrayMap。

SparseArray采用二分法的方式存儲數據,所以SparseArray內的元素時按照鍵從小到大排列的,SparseArray只接受int類型的鍵

put(int key, E value)//增? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? append(int key, E value)//增,其中的key是大于所有現有的鍵的數組,以便于提升性能? ? ? ? ? ??? E get(int key)//查? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??????? E get(int key, E valueIfKeyNotFound)//查? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? delete(int key)//刪? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? remove(int key)//刪,實際上remove和delete是一樣的,remove方法中調用了delete方法? ? ? setValueAt(int index, E value)//改? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? put(int key, E value)//改

ArrayMap,該類是在API19中出現的,單位了兼容低版本support.v4中也有ArrayMap類。ArrayMap在內部使用兩個數組進行工作,其中一個數組記錄key hash過后的順序列表,另外一個數組按key的順序記錄Key-Value值。首先要清楚ArrayMap針對于移動設備的優化是在內存上進行的優化,也就是說使用這個容器比起HashMap會占用更少的內存,因為ArrayMap中的內存占用是連續不間斷的,但隨著數組中元素的增多,查找訪問單個對象的花費也會跟著增長,同時ArrayMap的插入與刪除的效率是不夠高的,但如果你需要的是在一百這個數量級上時,則完全不用擔心這些。

以上是自己對集合知識學習的總結,如果有不正確的地方,感謝指正,我也會及時修改。后面也會逐漸完善這方面的知識分享給大家。

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

推薦閱讀更多精彩內容

  • 1、介紹Collection框架的結構Collection FrameWork如下:Collection├List...
    岳小川閱讀 277評論 0 0
  • Collection ├List │├LinkedList │├ArrayList │└Vector │└Stac...
    AndyZX閱讀 888評論 0 1
  • 集合類簡介 為什么出現集合類?面向對象語言對事物的體現都是以對象的形式,所以為了方便對多個對象的操作,就要對對象進...
    阿敏其人閱讀 1,435評論 0 7
  • title: java集合框架學習總結 tags:集合框架 categories:總結 date: 2017-03...
    行徑行閱讀 1,701評論 0 2
  • 3.3 集合 一方面, 面向對象語言對事物的體現都是以對象的形式,為了方便對多個對象的操作,就要對對象進行存儲。另...
    閆子揚閱讀 743評論 0 1