集合框架圖
Java集合框架主要包括兩種類型的容器款咖,一種是集合(Collection)何暮,存儲(chǔ)一個(gè)元素集合海洼,另一種是圖(Map),存儲(chǔ)鍵/值對映射坏逢。Collection接口又有3種子類型,List是整、Set和Queue民假,再下面是一些抽象類,最后是具體實(shí)現(xiàn)類阳欲,常用的有ArrayList陋率、LinkedList、HashSet瓦糟、LinkedHashSet、HashMap菩浙、LinkedHashMap等等。
Collection接口
Collection接口是處理對象集合的根接口劲蜻,其中定義了很多對元素進(jìn)行操作的方法,AbstractCollection是提供Collection部分實(shí)現(xiàn)的抽象類先嬉。
Collection接口里面定義的方法
- size(): int
- isEmpty: boolean
- contains(Object): bollean
- iterator(): Iterator<E>
- toArray(): Object[]
- toArray(T[])<T>: T[]
- add(E): boolean
- remove(Object) : boolean
- containsAll(Collection<?> ): boolean
- removeAll(Collection<?>): boolean
- removeIf(Predicate<? super E >): boolean
- retainAll(Collection<?>):boolean
- clear(): void
- equals(Object) : boolean
- hashCCode(): int
- spliterator(): Spliterator<E>
- stream(): Stream<E>
- parallelStream(): Steam<E>
List接口
List可以定義一個(gè)允許重復(fù)的有序集合,List接口主要是增加了面向位置的操作含懊,允許在指定位置上操作元素,同時(shí)增加了一個(gè)能夠雙向遍歷線性表的新列表迭代器ListIterator岔乔。AbstractList類提供了List接口的部分實(shí)現(xiàn)滚躯,AbstractSequentialList擴(kuò)展自AbstractList嘿歌,主要是提供對鏈表的支持茁影。可能最常用的類呼胚,ArrayList和LinkedList
ArrayList
用動(dòng)態(tài)數(shù)組存儲(chǔ)元素,這個(gè)數(shù)組可以動(dòng)態(tài)創(chuàng)建蝇更,如果元素個(gè)數(shù)超過了數(shù)組的容量,那么就創(chuàng)建一個(gè)更大的新數(shù)組年扩,并將當(dāng)前數(shù)組中的所有元素都復(fù)制到新數(shù)組中。LinkedList
LinkedList是在一個(gè)鏈表中存儲(chǔ)元素厨幻。ArrayList與LinkedList的差異
若只對單條數(shù)據(jù)插入或刪除,ArrayList的速度反而優(yōu)于LinkedList饭宾。但若是批量隨機(jī)的插入刪除數(shù)據(jù),LinkedList的速度大大優(yōu)于ArrayList. 因?yàn)锳rrayList每插入一條數(shù)據(jù)看铆,要移動(dòng)插入點(diǎn)及之后的所有數(shù)據(jù)盛末。
對于隨機(jī)訪問get和set,ArrayList覺得優(yōu)于LinkedList悄但,因?yàn)長inkedList要移動(dòng)指針。查找操作indexOf,lastIndexOf,contains等檐嚣,兩者差不多。
ArrayList線程不安全净嘀,查詢塊,因?yàn)槭菙?shù)組來構(gòu)成的挖藏。
Set接口
Set接口擴(kuò)展自Collection,它與List的不同之處在于岩臣,規(guī)定Set的實(shí)例不包含重復(fù)的元素溜嗜。在一個(gè)規(guī)則集內(nèi)架谎,一定不存在兩個(gè)相等的元素。AbstractSet是一個(gè)實(shí)現(xiàn)Set接口的抽象類土全,Set接口有三個(gè)具體實(shí)現(xiàn)類,分別是散列集HashSet裹匙、鏈?zhǔn)缴⒘屑疞inkedHashSet和樹形集TreeSet。
HashSet散列集
散列集HashSet是一個(gè)用于實(shí)現(xiàn)Set接口的具體類概页,可以使用它的無參構(gòu)造方法來創(chuàng)建空的散列集练慕,也可以由一個(gè)現(xiàn)有的集合創(chuàng)建散列集。在散列集中铃将,有兩個(gè)名詞需要關(guān)注,初始容量和客座率麸塞〗а茫客座率是確定在增加規(guī)則集之前,該規(guī)則集的飽滿程度弧哎,當(dāng)元素個(gè)數(shù)超過了容量與客座率的乘積時(shí),容量就會(huì)自動(dòng)翻倍撤嫩。輸出的時(shí)候是無序的,跟add()添加元素的順序無關(guān)序攘。LinkedHashSet鏈?zhǔn)缴⒘屑?br> LinkedHashSet是用一個(gè)鏈表實(shí)現(xiàn)來擴(kuò)展HashSet類,它支持對規(guī)則集內(nèi)的元素排序程奠。HashSet中的元素是沒有被排序的,而LinkedHashSet中的元素可以按照它們插入規(guī)則集的順序提取瞄沙。
TreeSet樹形集
TreeSet擴(kuò)展自AbstractSet慌核,并實(shí)現(xiàn)了NavigableSet申尼,AbstractSet擴(kuò)展自AbstractCollection,樹形集是一個(gè)有序的Set师幕,其底層是一顆樹,這樣就能從Set里面提取一個(gè)有序序列了霹粥。在實(shí)例化TreeSet時(shí),我們可以給TreeSet指定一個(gè)比較器Comparator來指定樹形集中的元素順序宗侦。
Queue接口
隊(duì)列是一種先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu),元素在隊(duì)列末尾添加矾利,在隊(duì)列頭部刪除。Queue接口擴(kuò)展自Collection男旗,并提供插入、提取察皇、檢驗(yàn)等操作泽台。
Queue接口方法
- add(E):
增加一個(gè)元索,如果隊(duì)列已滿,則拋出一個(gè)IIIegaISlabEepeplian異常 - offer(E):bolean
添加一個(gè)元素并返回true,如果隊(duì)列已滿怀酷,則返回false - poll(): E
移除并返問隊(duì)列頭部的元素,如果隊(duì)列為空,則返回null - remove(): E
移除并返回隊(duì)列頭部的元素,如果隊(duì)列為空蜕依,則拋出一個(gè)NoSuchElementException異常 - peek(): E
返回隊(duì)列頭部的元素,如果隊(duì)列為空,則返回null - element(): E
返回隊(duì)列頭部的元素,如果隊(duì)列為空样眠,則拋出一個(gè)NoSuchElementException異常
接口Deque,是一個(gè)擴(kuò)展自Queue的雙端隊(duì)列辫秧,它支持在兩端插入和刪除元素,因?yàn)長inkedList類實(shí)現(xiàn)了Deque接口茶没,所以通常我們可以使用LinkedList來創(chuàng)建一個(gè)隊(duì)列肌幽。PriorityQueue類實(shí)現(xiàn)了一個(gè)優(yōu)先隊(duì)列抓半,優(yōu)先隊(duì)列中元素被賦予優(yōu)先級(jí),擁有高優(yōu)先級(jí)的先被刪除笛求。
Map接口
Map是一種存儲(chǔ)鍵值對映射的容器類,在Map中鍵可以
任意類型的對象狡孔,但不能有重復(fù)的鍵,每個(gè)鍵都對應(yīng)一個(gè)值苗膝,真正存儲(chǔ)在圖中的是鍵值構(gòu)成的條目。
- Map存儲(chǔ)元素使用put方法辱揭,Collection使用add方法
- Map集合沒有直接取出元素的方法,而是先轉(zhuǎn)成Set集合问窃,在通過迭代獲取元素
- Map集合中鍵要保證唯一性
HashMap
HashMap是基于哈希表的Map接口的非同步實(shí)現(xiàn)完沪,繼承自AbstractMap,AbstractMap是部分實(shí)現(xiàn)Map接口的抽象類覆积。JDK1.8中,HashMap采用數(shù)組+鏈表+紅黑樹實(shí)現(xiàn)技健,當(dāng)鏈表長度超過閾值(8)時(shí),將鏈表轉(zhuǎn)換為紅黑樹雌贱,這樣大大減少了查找時(shí)間欣孤。
HashMap:線程不安全,速度快降传,允許存放null鍵。
關(guān)于HashMap與HashTable
相同:他們都是集合類婆排,用來存放java對象声旺。
區(qū)別:
- 歷史原因
Hashtable是基于陳舊的Dictionary類的腮猖,HashMap是jdk1.2之后引入的一個(gè)基于Map接口的一個(gè)實(shí)現(xiàn)。 - 同步性
Hashtable是線程同步的澈缺,而HashMap不是,他是異步的姐赡。因而Hashtable是線程安全的,HashMap非線程安全项滑。當(dāng)然因?yàn)榫€程安全涯贞,所以執(zhí)行效率低,HashMap非線程安全則執(zhí)行效率高肩狂,速度快。(如:多個(gè)線程去同時(shí)請求一個(gè)程序(如服務(wù)器)傻谁,則如果是線程安全則會(huì)用到鎖的概念,在程序響應(yīng)一個(gè)線程的時(shí)候會(huì)將該程序鎖定审磁,讓其他過來響應(yīng)的線程等待,并且是按序等待态蒂,所以他是安全的,不會(huì)造成程序崩潰)钾恢。如果不用到線程安全,則應(yīng)該首選HaspMap泉懦,這樣運(yùn)行效率會(huì)高一些。 - 值
HaspMap可以將空值null作為key或者value崩哩。但Hashtable是不能的。 - 方法
HashMap把Hashtable的contains方法去掉了邓嘹,改成containsvalue和containsKey;因?yàn)閏ontains方法容易讓人引起誤解汹押。
LinkedMap
LinkedHashMap繼承自HashMap,它主要是用鏈表實(shí)現(xiàn)來擴(kuò)展HashMap類鲸阻,HashMap中條目是沒有順序的,但是在LinkedHashMap中元素既可以按照它們插入圖的順序排序鸟悴,也可以按它們最后一次被訪問的順序排序。
TreeMap
TreeMap基于紅黑樹數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn)沛贪,鍵值可以使用Comparable或Comparator接口來排序。TreeMap繼承自AbstractMap利赋,同時(shí)實(shí)現(xiàn)了接口NavigableMap,而接口NavigableMap則繼承自SortedMap媚送。SortedMap是Map的子接口,使用它可以確保圖中的條目是排好序的塘偎。
在實(shí)際使用中,如果更新圖時(shí)不需要保持圖中元素的順序吟秩,就使用HashMap绽淘,如果需要保持圖中元素的插入順序或者訪問順序,就使用LinkedHashMap沪铭,如果需要使圖按照鍵值排序,就使用TreeMap伦意。
Iterator迭代器
迭代器是一種設(shè)計(jì)模式,它是一個(gè)對象驮肉,它可以遍歷并選擇序列中的對象已骇,而開發(fā)人員不需要了解該序列的底層結(jié)構(gòu)票编。迭代器通常被稱為“輕量級(jí)”對象卵渴,因?yàn)閯?chuàng)建它的代價(jià)小。并且只能單向移動(dòng)
迭代器可用與Collection框架內(nèi)的所有類型的集合浪读,由圖可以看出Collection是繼承了Iterator的。
- 為什么要用迭代器
一方面碘橘,迭代器的開銷開銷比較小,在訪問集合對象時(shí)候能節(jié)省內(nèi)存
另一方面仰禽,通過for循環(huán)來訪問集合對象的時(shí)候,不能對集合對象進(jìn)行刪操作吐葵,而迭代器可以。
Iterarot與ListIterator不同
- 使用范圍不同温峭,Iterator可以應(yīng)用于所有的集合,Set凤藏、List和Map和這些集合的子類型。而ListIterator只能用于List及其子類型清笨。
- ListIterator有add方法刃跛,可以向List中添加對象,而Iterator不能桨昙。
- ListIterator和Iterator都有hasNext()和next()方法,可以實(shí)現(xiàn)順序向后遍歷蛙酪,但是ListIterator有hasPrevious()和previous()方法,可以實(shí)現(xiàn)逆向(順序向前)遍歷桂塞。Iterator不可以。
- ListIterator可以定位當(dāng)前索引的位置,nextIndex()和previousIndex()可以實(shí)現(xiàn)汰瘫。Iterator沒有此功能。
- 都可實(shí)現(xiàn)刪除操作混弥,但是ListIterator可以實(shí)現(xiàn)對象的修改,set()方法可以實(shí)現(xiàn)蝗拿。Iterator僅能遍歷,不能修改哀托。