一、List接口
List是一個(gè)繼承于Collection的接口,即List是集合中的一種。List是有序的隊(duì)列,List中的每一個(gè)元素都有一個(gè)索引;第一個(gè)元素的索引值是0,往后的元素的索引值依次+1。和Set不同,List中允許有重復(fù)的元素。實(shí)現(xiàn)List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。
ArrayList
ArrayList是一個(gè)動(dòng)態(tài)數(shù)組,也是我們最常用的集合。它允許任何符合規(guī)則的元素插入甚至包括null。每一個(gè)ArrayList都有一個(gè)初始容量:
private static final int DEFAULT_CAPACITY = 10;
隨著容器中的元素不斷增加,容器的大小也會(huì)隨著增加。在每次向容器中增加元素的同時(shí)都會(huì)進(jìn)行容量檢查,當(dāng)快溢出時(shí),就會(huì)進(jìn)行擴(kuò)容操作。所以如果我們明確所插入元素的多少,最好指定一個(gè)初始容量值,避免過(guò)多的進(jìn)行擴(kuò)容操作而浪費(fèi)時(shí)間、效率。
size、isEmpty、get、set、iterator 和 listIterator 操作都以固定時(shí)間運(yùn)行。add 操作以分?jǐn)偟墓潭〞r(shí)間運(yùn)行,也就是說(shuō),添加 n 個(gè)元素需要 O(n) 時(shí)間(由于要考慮到擴(kuò)容,所以這不只是添加元素會(huì)帶來(lái)分?jǐn)偣潭〞r(shí)間開(kāi)銷那樣簡(jiǎn)單)。
ArrayList擅長(zhǎng)于隨機(jī)訪問(wèn)。同時(shí)ArrayList是非同步的。
LinkedList
同樣實(shí)現(xiàn)List接口的LinkedList與ArrayList不同,ArrayList是一個(gè)動(dòng)態(tài)數(shù)組,而LinkedList是一個(gè)雙向鏈表。所以它除了有ArrayList的基本操作方法外還額外提供了get,remove,insert方法在LinkedList的首部或尾部。
由于實(shí)現(xiàn)的方式不同,LinkedList不能隨機(jī)訪問(wèn),它所有的操作都是要按照雙重鏈表的需要執(zhí)行。在列表中索引的操作將從開(kāi)頭或結(jié)尾遍歷列表(從靠近指定索引的一端,節(jié)約一半時(shí)間)。這樣做的好處就是可以通過(guò)較低的代價(jià)在List中進(jìn)行插入和刪除操作。
與ArrayList一樣,LinkedList也是非同步的。如果多個(gè)線程同時(shí)訪問(wèn)一個(gè)List,則必須自己實(shí)現(xiàn)訪問(wèn)同步。一種解決方法是在創(chuàng)建List時(shí)構(gòu)造一個(gè)同步的List:
List list = Collections.synchronizedList(new LinkedList(…));
Vector
與ArrayList相似,但是Vector是同步的。所以說(shuō)Vector是線程安全的動(dòng)態(tài)數(shù)組。它的操作與ArrayList幾乎一樣。
Stack
Stack繼承自Vector,實(shí)現(xiàn)一個(gè)后進(jìn)先出的堆棧。Stack提供5個(gè)額外的方法使得Vector得以被當(dāng)作堆棧使用?;镜膒ush和pop方法,還有peek方法得到棧頂?shù)脑兀琫mpty方法測(cè)試堆棧是否為空,search方法檢測(cè)一個(gè)元素在堆棧中的位置。Stack剛創(chuàng)建后是空棧。
二、Set接口
Set是一個(gè)繼承于Collection的接口,Set是一種不包括重復(fù)元素的Collection。它維持它自己的內(nèi)部排序,所以隨機(jī)訪問(wèn)沒(méi)有任何意義。與List一樣,它同樣運(yùn)行null的存在但是僅有一個(gè)。由于Set接口的特殊性,所有傳入Set集合中的元素都必須不同,關(guān)于API方面。Set的API和Collection完全一樣。實(shí)現(xiàn)了Set接口的集合有:HashSet、TreeSet、LinkedHashSet、EnumSet。
HashSet
HashSet堪稱查詢速度最快的集合,因?yàn)槠鋬?nèi)部是以HashCode來(lái)實(shí)現(xiàn)的。集合元素可以是null,但只能放入一個(gè)null。它內(nèi)部元素的順序是由哈希碼來(lái)決定的,所以它不保證set的迭代順序;特別是它不保證該順序恒久不變。
TreeSet
TreeSet是二叉樹(shù)實(shí)現(xiàn)的,基于TreeMap,生成一個(gè)總是處于排序狀態(tài)的set,內(nèi)部以TreeMap來(lái)實(shí)現(xiàn),不允許放入null值。它是使用元素的自然順序?qū)υ剡M(jìn)行排序,或者根據(jù)創(chuàng)建Set時(shí)提供的 Comparator 進(jìn)行排序,具體取決于使用的構(gòu)造方法。
LinkedHashSet
LinkedHashSet集合同樣是根據(jù)元素的hashCode值來(lái)決定元素的存儲(chǔ)位置,但是它同時(shí)使用鏈表維護(hù)元素的次序。這樣使得元素看起 來(lái)像是以插入順序保存的,也就是說(shuō),當(dāng)遍歷該集合時(shí)候,LinkedHashSet將會(huì)以元素的添加順序訪問(wèn)集合的元素。LinkedHashSet在迭代訪問(wèn)Set中的全部元素時(shí),性能比HashSet好,但是插入時(shí)性能稍微遜色于HashSet。
三、Map接口
Map與List、Set接口不同,它是由一系列鍵值對(duì)組成的集合,提供了key到Value的映射。在Map中它保證了key與value之間的一一對(duì)應(yīng)關(guān)系。也就是說(shuō)一個(gè)key對(duì)應(yīng)一個(gè)value,所以它不能存在相同的key值,當(dāng)然value值可以相同。實(shí)現(xiàn)map的集合有:HashMap、HashTable、TreeMap、WeakHashMap。
HashMap
以哈希表數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn),查找對(duì)象時(shí)通過(guò)哈希函數(shù)計(jì)算其位置,它是為快速查詢而設(shè)計(jì)的,其內(nèi)部定義了一個(gè)hash表數(shù)組(Entry[] table),元素會(huì)通過(guò)哈希轉(zhuǎn)換函數(shù)將元素的哈希地址轉(zhuǎn)換成數(shù)組中存放的索引,如果有沖突,則使用散列鏈表的形式將所有相同哈希地址的元素串起來(lái),可能通過(guò)查看HashMap.Entry的源碼它是一個(gè)單鏈表結(jié)構(gòu)。
HashTable
也是以哈希表數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)的,解決沖突時(shí)與HashMap也一樣也是采用了散列鏈表的形式。HashTable繼承Dictionary類,實(shí)現(xiàn)Map接口。其中Dictionary類是任何可將鍵映射到相應(yīng)值的類(如 Hashtable)的抽象父類。每個(gè)鍵和每個(gè)值都是一個(gè)對(duì)象。在任何一個(gè) Dictionary 對(duì)象中,每個(gè)鍵至多與一個(gè)值相關(guān)聯(lián)。Map是”key-value鍵值對(duì)”接口。 HashTable采用”拉鏈法”實(shí)現(xiàn)哈希表不過(guò)性能比HashMap要低。
TreeMap
有序散列表,實(shí)現(xiàn)SortedMap接口,底層通過(guò)紅黑樹(shù)實(shí)現(xiàn)。
WeakHashMap
談WeakHashMap前先看一下Java中的引用(強(qiáng)度依次遞減)
1. 強(qiáng)引用:普遍對(duì)象聲明的引用,存在便不會(huì)GC
2. 軟引用:有用但并非必須,發(fā)生內(nèi)存溢出前,二次回收
3. 弱引用:只能生存到下次GC之前,無(wú)論是否內(nèi)存足夠
4. 虛引用:唯一目的是在這個(gè)對(duì)象被GC時(shí)能收到一個(gè)系統(tǒng)通知
以弱鍵實(shí)現(xiàn)的基于哈希表的Map。在 WeakHashMap 中,當(dāng)某個(gè)鍵不再正常使用時(shí),將自動(dòng)移除其條目。更精確地說(shuō),對(duì)于一個(gè)給定的鍵,其映射的存在并不阻止垃圾回收器對(duì)該鍵的丟棄,這就使該鍵成為可終止的,被終止,然后被回收。丟棄某個(gè)鍵時(shí),其條目從映射中有效地移除,因此,該類的行為與其他的 Map 實(shí)現(xiàn)有所不同。null值和null鍵都被支持。該類具有與HashMap類相似的性能特征,并具有相同的效能參數(shù)初始容量和加載因子。像大多數(shù)集合類一樣,該類是不同步的。
四、總結(jié)
1、List、Set都是繼承自Collection接口,Map則不是
2、List特點(diǎn):元素有放入順序,元素可重復(fù) ,Set特點(diǎn):元素?zé)o放入順序,元素不可重復(fù),重復(fù)元素會(huì)覆蓋掉,(注意:元素雖然無(wú)放入順序,但是元素在set中的位置是有該元素的HashCode決定的,其位置其實(shí)是固定的,加入Set 的Object必須定義equals()方法 ,另外list支持for循環(huán),也就是通過(guò)下標(biāo)來(lái)遍歷,也可以用迭代器,但是set只能用迭代,因?yàn)樗麩o(wú)序,無(wú)法用下標(biāo)來(lái)取得想要的值。)
3、Set和List對(duì)比:
Set:檢索元素效率低下,刪除和插入效率高,插入和刪除不會(huì)引起元素位置改變。
List:和數(shù)組類似,List可以動(dòng)態(tài)增長(zhǎng),查找元素效率高,插入刪除元素效率低,因?yàn)闀?huì)引起其他元素位置改變。
4、Map適合儲(chǔ)存鍵值對(duì)的數(shù)據(jù)
5、線程安全集合類與非線程安全集合類 :
· LinkedList、ArrayList、HashSet是非線程安全的,Vector是線程安全的;
· HashMap是非線程安全的,HashTable是線程安全的;
· StringBuilder是非線程安全的,StringBuffer是線程安全的。
更多關(guān)于“Java培訓(xùn)”的問(wèn)題,歡迎咨詢千鋒教育在線名師。千鋒已有十余年的培訓(xùn)經(jīng)驗(yàn),課程大綱更科學(xué)更專業(yè),有針對(duì)零基礎(chǔ)的就業(yè)班,有針對(duì)想提升技術(shù)的好程序員班,高品質(zhì)課程助理你實(shí)現(xiàn)java程序員夢(mèng)想。