Java集合相關(guān)

在Java開發(fā)中,會經(jīng)常使用到集合,那么何為集合呢?

集合是用于存儲批量數(shù)據(jù)的容器工具阴绢,可以將其看做一個(gè)可變長度的數(shù)組。

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

Collection

我們先從Collection接口說起,接口Collection是collection層次結(jié)構(gòu)的根接口腺兴,表示一組對象左电,一些collection是允許重復(fù),一些則不可以含长。一些是有序的券腔,而一些則是無序的伏穆。

所有通用的Collection實(shí)現(xiàn)類(通常通過它的一個(gè)子接口間接實(shí)現(xiàn)Collection)應(yīng)該提供兩個(gè)“標(biāo)準(zhǔn)”構(gòu)造方法:一個(gè)是 void(無參數(shù))構(gòu)造方法拘泞,用于創(chuàng)建空 collection;另一個(gè)是帶有Collection類型單參數(shù)的構(gòu)造方法枕扫,用于創(chuàng)建一個(gè)具有與其參數(shù)相同元素新的 collection陪腌。實(shí)際上,后者允許用戶復(fù)制任何 collection烟瞧,以生成所需實(shí)現(xiàn)類型的一個(gè)等效 collection诗鸭。盡管無法強(qiáng)制執(zhí)行此約定(因?yàn)榻涌诓荒馨瑯?gòu)造方法),但是 Java 平臺庫中所有通用的Collection實(shí)現(xiàn)都遵從它参滴∏堪叮——官網(wǎng)介紹

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

圖一 Collection

Set接口

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

HashSet

對于HashSet砾赔,是基于HashMap(我們將會在后面介紹)實(shí)現(xiàn)的蝌箍。HashSet底層采用HashMap來保存所有元素。主要用來做高性能的集運(yùn)算暴心,為快速查找而設(shè)計(jì)妓盲。存入HashSet的對象必須重寫hashCode()方法。

當(dāng)我們向HashSet集合添加元素時(shí)专普,它是按照hash算法來存儲集合中的元素悯衬。首先HashSet會調(diào)用該對象的hashCode()方法來獲取到該對象的hashCode值,然后根據(jù)hashCode值決定該對象在Set集合中的存儲位置檀夹。HashSet集合判斷兩個(gè)元素相等的標(biāo)準(zhǔn)是兩個(gè)對象通過equals方法比較相等筋粗,同時(shí)兩個(gè)元素的hashCode()方法返回值也相等策橘。因此如果兩個(gè)元素通過equals方法比較返回為true,但它們通過hashCode()方法返回的值的比較不相等娜亿,那么HashSet會將這兩個(gè)元素存儲在不同的位置役纹,仍然能夠添加成功。

TreeSet

TreeSet是一種可指定排序方式的Set集合暇唾。其底層數(shù)據(jù)結(jié)構(gòu)是二叉樹促脉。通過比較兩元素的結(jié)果是否為0來保證元素的唯一性。

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

方式一:讓元素自身具備比較性策州。只要讓元素實(shí)現(xiàn)Comparable接口瘸味,并覆蓋compareTo方法即可馍驯,當(dāng)compareT方法的返回值為0時(shí)帆锋,就是相同元素。

方式二:讓集合自身具備比較性嫡秕。該方式通過自定義比較器來實(shí)現(xiàn)孽糖,自定義類實(shí)現(xiàn)Comparator接口枯冈,覆蓋compare方法,將該Comparator接口實(shí)現(xiàn)類的對象作為參數(shù)傳遞給TreeSet的構(gòu)造方法即可办悟。


List接口

List類型的集合存儲的元素時(shí)有序且可重復(fù)尘奏。

ArrayList

ArrayList底層采用一個(gè)可變長度的數(shù)組實(shí)現(xiàn),可存儲所有的元素病蛉,包括null炫加。由于其實(shí)現(xiàn)了Serializable接口,所以其支持序列化铺然。又由于其實(shí)現(xiàn)了RandomAccess接口俗孝,所以支持快速隨機(jī)訪問。ArrayList集合存儲的元素按照存入的先后順序排列元素魄健,也就是說先進(jìn)先出赋铝。

每個(gè)ArrayList實(shí)例都有一個(gè)容量,即用于存儲元素的數(shù)組的大小沽瘦,這個(gè)容量可隨著不斷添加新元素而自動(dòng)增加革骨,。但是增長算法并沒有定義其垄。當(dāng)需要插入大量元素的時(shí)候苛蒲,再插入前可以調(diào)用ensureCapacity方法來增加ArrayList的容量以提高插入效率。

ArrayList歲支持快速隨機(jī)訪問绿满,但向集合中插入與移除元素的操作速度很慢臂外。

LinkedList

LinkList在的底層是一個(gè)鏈表結(jié)構(gòu),因此LinkList對于集合增刪操作來說會更加占有優(yōu)勢,只需要對指針(注:在Java中沒有指針的概念漏健,這里是可以更形象地進(jìn)行說明)操作即可嚎货。又因?yàn)殒湵淼慕Y(jié)構(gòu),LinkList可以被用作堆棧蔫浆,隊(duì)列或雙向隊(duì)列殖属。

Vector

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

Stack

Stack集合繼承于Vector類瓦盛,Stack底層是一個(gè)堆棧結(jié)構(gòu)洗显,遵循后進(jìn)先出(LIFO)原則,只能在一端執(zhí)行插入操作(稱為入棧)或刪除操作(稱為出棧)

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


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


圖二 Map

Map接口

Map類型的集合以鍵值對的形式存儲數(shù)據(jù)。不允許鍵的重復(fù)和從鍵到值的一對多映射嘱吗。

HashMap

在HashMao內(nèi)部通過一個(gè)哈希表來管理所有元素玄组,同上文敘述的HashSet類似(其實(shí)應(yīng)該說HashSet同HashMap類似),通過hashCode()方法和equals()方法來保證鍵的唯一性谒麦。也因此HashMap通過鍵的hashCode來快速的存取元素俄讹。

LinkedHashMap

LinkedHashMap繼承于HashMap,在底層是以哈希表和鏈接列表相結(jié)合而實(shí)現(xiàn)的.該集合類型保留插入順序绕德,如果需要輸入順序與輸出順序相同患膛,可以采用此集合。在LinkedHashMap內(nèi)部有兩種排序方式迁匠,一種是插入順序(默認(rèn))剩瓶,一種是訪問順序(即近期訪問最少到近期訪問最多的順序)驹溃,這兩種方式通過一個(gè)布爾值accessOrder進(jìn)行切換城丧,在LinkedHashMap的構(gòu)造方法publicLinkedHashMap(intinitialCapacity,floatloadFactor,booleanaccessOrder)?{ ??super(initialCapacity,?loadFactor); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??this.accessOrder?=?accessOrder;}?中,如果accessOrder為true豌鹤,表示按照訪問順序存儲元素亡哄,如果為false表示按照插入順序訪問元素。

Hashtable

同樣HashMap在底層是通過一個(gè)哈希表來實(shí)現(xiàn)的布疙。

Properties

Properties繼承于Hashtable蚊惯,該類表示一個(gè)持久的屬性值,可保存在流中或從流中加載灵临。屬性列表中每個(gè)鍵及其對應(yīng)值都是一個(gè)字符串截型。該類主要用于讀取Java中的配置文件,在Java中儒溉,其配置文件常為.properties文件宦焦,格式為文本文件,文件的內(nèi)容的格式是“鍵=值”的格式,文本注釋信息可以用"#"來注釋波闹。了解Properties的詳細(xì)用法酝豪,點(diǎn)我

TreeMap

TreeMap實(shí)現(xiàn)了SortedMap接口精堕,該集合根據(jù)鍵的自然順序進(jìn)行排序孵淘,或根據(jù)創(chuàng)建集合時(shí)傳入的Comparator進(jìn)行排序,具體取決于使用的構(gòu)造方法歹篓。

各種集合的比較

1.同步性

以上介紹的集合中瘫证,除Vector、Stack庄撮、HashTable和Properties外痛悯,其他集合類型(HashSet、TreeSet重窟、ArrayList载萌、LinkedList、LinkedHashMap巡扇、TreeMap)都是非線程安全的扭仁。那么當(dāng)多個(gè)線程同時(shí)訪問這些非線程的集合類型時(shí),我們必須自己實(shí)現(xiàn)訪問同步厅翔,一種解決方案是在構(gòu)造這些集合時(shí)構(gòu)造一個(gè)同步集合乖坠,通過Collections類的靜態(tài)方法synchronizedCollection() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?synchronizedList() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?synchronizedMap() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?synchronizedSet() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?synchronizedSortedMap() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?synchronizedSortedSet()

2.ArrayList與Vector的比較

同步性方面,如1所述刀闷,Vector不需要自己實(shí)現(xiàn)同步方案熊泵,而ArrayList需要自己實(shí)現(xiàn)同步方案。ArrayList和Vector都是使用可變長數(shù)組來保存數(shù)據(jù)甸昏,當(dāng)數(shù)組空間不足時(shí)顽分,兩者就需要擴(kuò)展其大小,ArrayList增加50%的大小施蜜,而Vector在默認(rèn)情況下增長一倍的大小卒蘸,但Vector可以自己設(shè)定這個(gè)增長幅度,在這方面Vector確實(shí)是有優(yōu)勢的翻默,根據(jù)情況設(shè)定增長幅度缸沃,對程序的性能來說會更加友好。

3.LinkedList與ArrayList修械、Vector的比較

這三種集合類型都支持快速隨機(jī)訪問趾牧,在集合的首或末對元素進(jìn)行更重操作,三者并沒有什么的區(qū)別肯污,但當(dāng)從其他任意位置對元素進(jìn)行操作翘单,在性能上就會產(chǎn)生很大的差異梯皿。上文有敘述到LinkList是一個(gè)鏈表結(jié)構(gòu),在任意位置的對元素的操作都在一個(gè)常數(shù)級的時(shí)間县恕,而Arrayl與Vecotr卻頗為費(fèi)時(shí)东羹。

4.HashMap和Hashtable的區(qū)別

Hashtable與HashMap類似,但Hashtable不允許鍵與值為null忠烛,HashMap卻允許属提。Hashtable是線程安全的,HashMap是縣城非安全的美尸。相比較下冤议,HashMap比Hashtable效率要高下,所以要根據(jù)具體情況選擇使用师坎。恕酸。

5.TreeMap和HashMap的比較

針對于TreeMap,HashMap使用起來性能更好胯陋,因?yàn)樵贖ashMap的構(gòu)造方法中蕊温,可以自己調(diào)優(yōu)初始容量和負(fù)載因子,這樣我們就可以根據(jù)具體的開發(fā)環(huán)境去優(yōu)化我們的HashMap遏乔。TreeMap可以自定義順序遍歷元素义矛,這更是與使用在需要具體排序的情況下。但是TreeMap的性能不是很好盟萨,TreeMap的get操作的時(shí)間復(fù)雜度是O(log(n))凉翻,針對于HashMap的O(1)差的還是比較多的。因此為了中和兩者捻激,出現(xiàn)了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類效率耗時(shí)是Map或Set的十倍左右鞭达。

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

添加 HashSet效率最高畴蹭,LinkedList最低坦仍,HashXXX和TreeXXX效率都比較高,這里ArrayList效率較低叨襟,整體相差不大繁扎。

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

查找 仍然是HashSet性能最好右犹,LinkedList最低提澎,性能較差的是ArrayList,其他的均表現(xiàn)很好念链。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ——摘自Adroid中文網(wǎng)

請根據(jù)具體情況具體選擇盼忌。

7.移動(dòng)開發(fā)給出的建議

在谷歌官方推出的Android性能優(yōu)化典范系列視頻中提到,Android為移動(dòng)操作系統(tǒng)特意編寫了一些更加高效的容器掂墓,其中包括SparseArray和ArrayMap碴犬。

SparseArray采用二分法的方式存儲數(shù)據(jù),所以SparseArray內(nèi)的元素時(shí)按照鍵從小到大排列的梆暮,SparseArray只接受int類型的鍵

put(int key, E value)//增? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? append(int key, E value)//增服协,其中的key是大于所有現(xiàn)有的鍵的數(shù)組,以便于提升性能? ? ? ? ? ??? E get(int key)//查? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??????? E get(int key, E valueIfKeyNotFound)//查? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? delete(int key)//刪? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? remove(int key)//刪啦粹,實(shí)際上remove和delete是一樣的偿荷,remove方法中調(diào)用了delete方法? ? ? setValueAt(int index, E value)//改? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? put(int key, E value)//改

ArrayMap,該類是在API19中出現(xiàn)的唠椭,單位了兼容低版本support.v4中也有ArrayMap類跳纳。ArrayMap在內(nèi)部使用兩個(gè)數(shù)組進(jìn)行工作,其中一個(gè)數(shù)組記錄key hash過后的順序列表贪嫂,另外一個(gè)數(shù)組按key的順序記錄Key-Value值寺庄。首先要清楚ArrayMap針對于移動(dòng)設(shè)備的優(yōu)化是在內(nèi)存上進(jìn)行的優(yōu)化,也就是說使用這個(gè)容器比起HashMap會占用更少的內(nèi)存力崇,因?yàn)锳rrayMap中的內(nèi)存占用是連續(xù)不間斷的斗塘,但隨著數(shù)組中元素的增多,查找訪問單個(gè)對象的花費(fèi)也會跟著增長亮靴,同時(shí)ArrayMap的插入與刪除的效率是不夠高的馍盟,但如果你需要的是在一百這個(gè)數(shù)量級上時(shí),則完全不用擔(dān)心這些茧吊。

以上是自己對集合知識學(xué)習(xí)的總結(jié)贞岭,如果有不正確的地方八毯,感謝指正,我也會及時(shí)修改瞄桨。后面也會逐漸完善這方面的知識分享給大家话速。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市芯侥,隨后出現(xiàn)的幾起案子泊交,更是在濱河造成了極大的恐慌,老刑警劉巖筹麸,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件活合,死亡現(xiàn)場離奇詭異,居然都是意外死亡物赶,警方通過查閱死者的電腦和手機(jī)白指,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來酵紫,“玉大人告嘲,你說我怎么就攤上這事〗钡兀” “怎么了橄唬?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長参歹。 經(jīng)常有香客問我仰楚,道長,這世上最難降的妖魔是什么犬庇? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任僧界,我火速辦了婚禮,結(jié)果婚禮上臭挽,老公的妹妹穿的比我還像新娘捂襟。我一直安慰自己,他們只是感情好欢峰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布葬荷。 她就那樣靜靜地躺著,像睡著了一般纽帖。 火紅的嫁衣襯著肌膚如雪宠漩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天抛计,我揣著相機(jī)與錄音哄孤,去河邊找鬼。 笑死吹截,一個(gè)胖子當(dāng)著我的面吹牛瘦陈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播波俄,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼晨逝,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了懦铺?” 一聲冷哼從身側(cè)響起捉貌,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎冬念,沒想到半個(gè)月后趁窃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡急前,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年醒陆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片裆针。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡刨摩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出世吨,到底是詐尸還是另有隱情澡刹,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布耘婚,位于F島的核電站罢浇,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏沐祷。R本人自食惡果不足惜嚷闭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望戈轿。 院中可真熱鬧凌受,春花似錦、人聲如沸思杯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽色乾。三九已至誊册,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間暖璧,已是汗流浹背案怯。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留澎办,地道東北人嘲碱。 一個(gè)月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓金砍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親麦锯。 傳聞我的和親對象是個(gè)殘疾皇子恕稠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容