(1)Collection:集合層次中的根接口,JDK 沒有提供這個(gè)接口直接的實(shí)現(xiàn)類。
(2)Set:不能包含重復(fù)的元素。
(3) List:是一個(gè)有序的集合,可以包含重復(fù)的元素。提供了按索引訪問(wèn)的方式。
(4)Map:包含了 key-value 對(duì)。Map 不能包含重復(fù)的 key。
List的主要特征使其元素已先行方式存儲(chǔ),集合中允許存放重復(fù)對(duì)象。List接口主要的實(shí)現(xiàn)類包括:
(1)ArrayList:代表長(zhǎng)度可變的數(shù)組。允許對(duì)元素進(jìn)行快速的隨機(jī)訪問(wèn),但是向ArrayList中插入與刪除元素的速度較慢。
(2)LinkedList :在實(shí)現(xiàn)中采用鏈表數(shù)據(jù)結(jié)構(gòu),元素之間是雙鏈接。對(duì)順序訪問(wèn)進(jìn)行了優(yōu)化,向List中插入和刪除元素的速度較快,隨機(jī)訪問(wèn)速度則相對(duì)較慢,隨機(jī)訪問(wèn)是指檢索位于特定索引位置元素,當(dāng)需要快速插入和刪除時(shí)LinkedList成為L(zhǎng)ist中的不二選擇。
(3)Vector :是ArrayList的線程安全版本,性能比ArrayList要低,現(xiàn)在已經(jīng)很少使用。
3.2.1、ArrayList是個(gè)集合
集合是可以往里面添東西的,用add(E e)方法往里面加(把E都看做Object)
例子:ArrayList類中的add和get方法(add方法向集合中添加數(shù)據(jù),get方法將集合中指定下標(biāo)位置的數(shù)據(jù)取出)
(1)size()方法,返回集合中的元素個(gè)數(shù),類似于數(shù)組中的length屬性
(2)clear()方法,將集合中的所有元素都給清除
(3)isEmpty()方法判斷集合是否為空,為空返回true
(4)remove(int index)方法是刪除集合中指定位置的元素,清除的原理是你清除了第一個(gè)后,后面的元素往前移,第一個(gè)變第0個(gè)了,原來(lái)第三個(gè)元素就沒啦
(5)remove(Object ob)是remove的重載,一個(gè)是根據(jù)索引來(lái)刪除,一個(gè)是根據(jù)具體對(duì)象來(lái)刪除,比如remove('Hello');
(6)indexOf(Obejct ob)判斷某個(gè)元素在索引的第幾個(gè)位置上。
在數(shù)組中查看數(shù)組元素個(gè)數(shù),用數(shù)組的length屬性,在集合中查看集合元素個(gè)數(shù),用集合的size()方法。
3.2.2、ArrayList使用范例
ArrayList遍歷方法1
Evankaka
林炳文
文炳林
秀秀
Evankaka
小紅
ArrayList遍歷方法2
Evankaka
林炳文
文炳林
秀秀
Evankaka
小紅
ArrayList遍歷方法3
Evankaka
林炳文
文炳林
秀秀
Evankaka
小紅
ArrayList刪除元素后的遍歷
林炳文
文炳林
Evankaka
小紅
3.2.3、ArrayList注意
(1)使用Iterator迭代集合過(guò)程中,不可修改集合元素,否則會(huì)引發(fā)異常。并且Iterator只能向后迭代
(2)如果你想在循環(huán)過(guò)程中去掉某個(gè)元素,只能調(diào)用it.remove方法, 不能使用list.remove方法, 否則一定出并發(fā)訪問(wèn)的錯(cuò)誤.
LinkedList類是鏈表節(jié)點(diǎn)各種操作的實(shí)現(xiàn),LinkedList類實(shí)現(xiàn)了一個(gè)帶有頭尾引用的通用型雙向鏈表。注意,此實(shí)現(xiàn)不是同步的。如果多個(gè)線程同時(shí)訪問(wèn)列表,而其中至少一個(gè)線程從結(jié)構(gòu)上修改了該列表,則它必須保持外部同步。(結(jié)構(gòu)修改指添加或刪除一個(gè)或多個(gè)元素的任何操作;僅設(shè)置元素的值不是結(jié)構(gòu)修改。)這一般通過(guò)對(duì)自然封裝該列表的對(duì)象進(jìn)行同步操作來(lái)完成。如果不存在這樣的對(duì)象,則應(yīng)該使用 Collections.synchronizedList 方法來(lái)“包裝”該列表。最好在創(chuàng)建時(shí)完成這一操作,以防止對(duì)列表進(jìn)行意外的不同步訪問(wèn)。
set集合中多個(gè)對(duì)象之間沒有明顯的順序,set與Collection的結(jié)構(gòu)基本上完全一樣,不同在于set不能包含重復(fù)元素。Set判斷兩個(gè)對(duì)象相同不是使用==運(yùn)算符,而是根據(jù)equals方法。也就是說(shuō)主要兩個(gè)對(duì)象用equals方法比較返回true,Set就不會(huì)接受這兩個(gè)對(duì)象。 HashSet是Set接口的典型實(shí)現(xiàn),大多數(shù)時(shí)候使用Set集合就是使用這個(gè)類。
HashSet按hash算法來(lái)存儲(chǔ)集合中的元素,因此具有很好的存儲(chǔ)和查找性能。
HaseSet具有以下特點(diǎn):
● 不能保證元素的排列順序,順序有可能發(fā)生變化
● HashSet不是同步的,如果多個(gè)線程訪問(wèn)同一個(gè)HashSet,要注意線程安全問(wèn)題
● 集合元素值可以為null
當(dāng)向HashSet集合中存入一個(gè)元素時(shí),HashSet會(huì)調(diào)用該對(duì)象的hashCode()方法來(lái)得到該對(duì)象的hashCode值,然后根據(jù)該值來(lái)決定該對(duì)象在HashSet中的存儲(chǔ)位置。如果有兩個(gè)元素通過(guò)equals方法比較返回true,但它們的hashCode方法返回值不相等,HashSet將會(huì)把它們存儲(chǔ)在不同的位置。也就是說(shuō)HashSet集合判斷兩個(gè)元素相等的標(biāo)準(zhǔn)是兩個(gè)對(duì)象通過(guò)equals方法比較相等,并且兩個(gè)對(duì)象的hashCode方法返回值也相等。
使用范例:
開始:size=5
4.0
1st
3
2nd
Mon Feb 16 20:52:17 CST 2015
移除元素后:size=4
[4.0, 1st, 3, Mon Feb 16 20:52:17 CST 2015]
4.2 TreeSet
TreeSet描述的是Set的一種變體——可以實(shí)現(xiàn)排序等功能的集合,它在將對(duì)象元素添加到集合中時(shí)會(huì)自動(dòng)按照某種比較規(guī)則將其插入到有序的對(duì)象序列中,并保證該集合元素組成時(shí)刻按照“升序”排列。
使用范例:
結(jié)果:
apple
banana
grape
orange
將鍵映射到值的對(duì)象。一個(gè)映射不能包含重復(fù)的鍵;每個(gè)鍵最多只能映射到一個(gè)值。此接口取代 Dictionary 類,后者完全是一個(gè)抽象類,而不是一個(gè)接口。
Map 接口提供三種collection 視圖,允許以鍵集、值集或鍵-值映射關(guān)系集的形式查看某個(gè)映射的內(nèi)容。映射順序 定義為迭代器在映射的 collection 視圖上返回其元素的順序。某些映射實(shí)現(xiàn)可明確保證其順序,如 TreeMap 類;另一些映射實(shí)現(xiàn)則不保證順序,如HashMap 類。
注:將可變對(duì)象用作映射鍵時(shí)必須格外小心。當(dāng)對(duì)象是映射中某個(gè)鍵時(shí),如果以影響 equals 比較的方式更改了對(duì)象的值,則映射的行為將是不確定的。此項(xiàng)禁止的一種特殊情況是不允許某個(gè)映射將自身作為一個(gè)鍵包含。雖然允許某個(gè)映射將自身作為值包 含,但請(qǐng)格外小心:在這樣的映射上 equals 和 hashCode 方法的定義將不再是明確的。
所有通用的映射實(shí)現(xiàn)類應(yīng)該提供兩個(gè)“標(biāo)準(zhǔn)的”構(gòu)造方法:一個(gè) void (無(wú) 參數(shù))構(gòu)造方法,用于創(chuàng)建空映射;一個(gè)是帶有單個(gè) Map 類型參數(shù)的構(gòu)造方法,用于創(chuàng)建一個(gè)與其參數(shù)具有相同鍵-值映射關(guān)系的新映射。實(shí)際上,后一個(gè)構(gòu)造方法允許用戶復(fù)制任意映射,生成所需類的一個(gè)等價(jià)映射。盡 管無(wú)法強(qiáng)制執(zhí)行此建議(因?yàn)榻涌诓荒馨瑯?gòu)造方法),但是 JDK 中所有通用的映射實(shí)現(xiàn)都遵從它。
此接口中包含的“破壞”方法可修改其操作的映射,如果此映射不支持該操作,這些方法將拋出 UnsupportedOperationException。如果是這樣,那么在調(diào)用對(duì)映射無(wú)效時(shí),這些方法可以(但不要求)拋出 UnsupportedOperationException。例如,如果某個(gè)不可修改的映射(其映射關(guān)系是“重疊”的)為空,則對(duì)該映射調(diào)用 putAll(Map) 方法時(shí),可以(但不要求)拋出異常。
某些映射實(shí)現(xiàn)對(duì)可能包含的鍵和值有所限制。例如,某些實(shí)現(xiàn)禁止 null 鍵和值,另一些則對(duì)其鍵的類型有限制。嘗試插入不合格的鍵或值將拋出一個(gè)未經(jīng)檢查的異常,通常是 NullPointerException 或 ClassCastException。試圖查詢是否存在不合格的鍵或值可能拋出異常,或者返回 false;某些實(shí)現(xiàn)將表現(xiàn)出前一種行為,而另一些則表現(xiàn)后一種。一般來(lái)說(shuō),試圖對(duì)不合格的鍵或值執(zhí)行操作且該操作的完成不會(huì)導(dǎo)致不合格的元素被插入映射 中時(shí),將可能拋出一個(gè)異常,也可能操作成功,這取決于實(shí)現(xiàn)本身。這樣的異常在此接口的規(guī)范中標(biāo)記為“可選”。
此接口是 Java Collections Framework 的成員。
Collections Framework 接口中的很多方法是根據(jù) equals 方法定義的。例如,containsKey(Object key) 方法的規(guī)范中寫道:“當(dāng)且僅當(dāng)此映射包含針對(duì)滿足 (key==null ? k==null : key.equals(k)) 的鍵 k 的映射關(guān)系時(shí),返回 true”。不 應(yīng)將此規(guī)范解釋為:調(diào)用具有非空參數(shù) key 的 Map.containsKey 將導(dǎo)致對(duì)任意的鍵 k 調(diào)用 key.equals(k)。實(shí)現(xiàn)可隨意進(jìn)行優(yōu)化,以避免調(diào)用 equals,例如,可首先比較兩個(gè)鍵的哈希碼(Object.hashCode() 規(guī)范保證哈希碼不相等的兩個(gè)對(duì)象不會(huì)相等)。一般來(lái)說(shuō),只要實(shí)現(xiàn)者認(rèn)為合適,各種 Collections Framework 接口的實(shí)現(xiàn)可隨意利用底層 Object 方法的指定行為。
Map 提供了一個(gè)更通用的元素存儲(chǔ)方法。Map 集合類用于存儲(chǔ)元素對(duì)(稱作“鍵”和“值”),其中每個(gè)鍵映射到一個(gè)值。從概念上而言,您可以將 List 看作是具有數(shù)值鍵的 Map。而實(shí)際上,除了 List 和 Map 都在定義 java.util 中外,兩者并沒有直接的聯(lián)系。本文將著重介紹核心 Java 發(fā)行套件中附帶的 Map,同時(shí)還將介紹如何采用或?qū)崿F(xiàn)更適用于您應(yīng)用程序特定數(shù)據(jù)的專用 Map。
5.1、了解 Map 接口和方法
Java 核心類中有很多預(yù)定義的 Map 類。在介紹具體實(shí)現(xiàn)之前,我們先介紹一下 Map 接口本身,以便了解所有實(shí)現(xiàn)的共同點(diǎn)。Map 接口定義了四種類型的方法,每個(gè) Map 都包含這些方法。下面,我們從兩個(gè)普通的方法開始對(duì)這些方法加以介紹。
表 1:覆蓋的方法。我們將這 Object 的這兩個(gè)方法覆蓋,以正確比較 Map 對(duì)象的等價(jià)性。
equals(Object o) | 比較指定對(duì)象與此 Map 的等價(jià)性 |
hashCode() | 返回此 Map 的哈希碼 |
5.2、Map 構(gòu)建
Map 定義了幾個(gè)用于插入和刪除元素的變換方法。
表 2:Map 更新方法: 可以更改 Map 內(nèi)容。
clear() | 從 Map 中刪除所有映射 |
remove(Object key) | 從 Map 中刪除鍵和關(guān)聯(lián)的值 |
put(Object key, Object value) | 將指定值與指定鍵相關(guān)聯(lián) |
clear() | 從 Map 中刪除所有映射 |
putAll(Map t) | 將指定 Map 中的所有映射復(fù)制到此 map |
盡管您可能注意到,縱然假設(shè)忽略構(gòu)建一個(gè)需要傳遞給 putAll() 的 Map 的開銷,使用 putAll() 通常也并不比使用大量的 put() 調(diào)用更有效率,但 putAll() 的存在一點(diǎn)也不稀奇。這是因?yàn)?,putAll() 除了迭代 put() 所執(zhí)行的將每個(gè)鍵值對(duì)添加到 Map 的算法以外,還需要迭代所傳遞的 Map 的元素。但應(yīng)注意,putAll() 在添加所有元素之前可以正確調(diào)整 Map 的大小,因此如果您未親自調(diào)整 Map 的大小(我們將對(duì)此進(jìn)行簡(jiǎn)單介紹),則 putAll() 可能比預(yù)期的更有效。
5.3、查看 Map
迭代 Map 中的元素不存在直接了當(dāng)?shù)姆椒?。如果要查詢某個(gè) Map 以了解其哪些元素滿足特定查詢,或如果要迭代其所有元素(無(wú)論原因如何),則您首先需要獲取該 Map 的“視圖”。有三種可能的視圖。
前兩個(gè)視圖均返回 Set 對(duì)象,第三個(gè)視圖返回 Collection 對(duì)象。就這兩種情況而言,問(wèn)題到這里并沒有結(jié)束,這是因?yàn)槟鸁o(wú)法直接迭代 Collection 對(duì)象或 Set 對(duì)象。要進(jìn)行迭代,您必須獲得一個(gè) Iterator 對(duì)象。因此,要迭代 Map 的元素,必須進(jìn)行比較煩瑣的編碼
值得注意的是,這些對(duì)象(Set、Collection 和 Iterator)實(shí)際上是基礎(chǔ) Map 的視圖,而不是包含所有元素的副本。這使它們的使用效率很高。另一方面,Collection 或 Set 對(duì)象的 toArray() 方法卻創(chuàng)建包含 Map 所有元素的數(shù)組對(duì)象,因此除了確實(shí)需要使用數(shù)組中元素的情形外,其效率并不高。
5.4、遍歷map輸出結(jié)果如下
===================通過(guò)Map.keySet遍歷key和value:===================
key= third and value= wenwen
key= first and value= linlin2
key= second and value= bingbing
===================通過(guò)Map.entrySet使用iterator遍歷key和value:===================
key= third and value= wenwen
key= first and value= linlin2
key= second and value= bingbing
===================通過(guò)Map.entrySet遍歷key和value:===================
key= third and value= wenwen
key= first and value= linlin2
key= second and value= bingbing
===================通過(guò)Map.values()遍歷所有的value:===================
value= wenwen
value= linlin2
value= bingbing
聯(lián)系客服