在 Java2中,有一套設計優(yōu)良的接口和類(lèi)組成了Java集合框架Collection,使程序員操作成批的數據或對象元素極為方便。這些接口和類(lèi)有很多對抽象數據類(lèi)型操作的API,而這是我們常用的且在數據結構中熟知的。例如Map,Set,List等。并且Java用面向對象的設計對這些數據結構和算法進(jìn)行了封裝,這就極大的減化了程序員編程時(shí)的負擔。程序員也可以以這個(gè)集合框架為基礎,定義更高級別的數據抽象,比如棧、隊列和線(xiàn)程安全的集合等,從而滿(mǎn)足自己的需要。
Java2的集合框架,抽其核心,主要有三種:List、Set和Map。如下圖所示:
需要注意的是,這里的 Collection、List、Set和Map都是接口(Interface),不是具體的類(lèi)實(shí)現。 List lst = new ArrayList(); 這是我們平常經(jīng)常使用的創(chuàng )建一個(gè)新的List的語(yǔ)句,在這里, List是接口,ArrayList才是具體的類(lèi)。
常用集合類(lèi)的繼承結構如下:
Collection<--List<--Vector
Collection<--List<--ArrayList
Collection<--List<--LinkedList
Collection<--Set<--HashSet
Collection<--Set<--HashSet<--LinkedHashSet
Collection<--Set<--SortedSet<--TreeSet
Map<--SortedMap<--TreeMap
Map<--HashMap
-----------------------------------------------SB分割線(xiàn)------------------------------------------
List: List是有序的Collection,使用此接口能夠精確的控制每個(gè)元素插入的位置。用戶(hù)能夠使用索引(元素在List中的位置,類(lèi)似于數組下 >標)來(lái)訪(fǎng)問(wèn)List中的元素,這類(lèi)似于Java的數組。
Vector: 基于數組(Array)的List,其實(shí)就是封裝了數組所不具備的一些功能方便我們使用,所以它難易避免數組的限制,同時(shí)性能也不可能超越數組。所以,在可能的情況下,我們要多運用數組。另外很重要的一點(diǎn)就是Vector是線(xiàn)程同步的(sychronized)的,這也是Vector和ArrayList 的一個(gè)的重要區別。
ArrayList: 同Vector一樣是一個(gè)基于數組上的鏈表,但是不同的是ArrayList不是同步的。所以在性能上要比Vector好一些,但是當運行到多線(xiàn)程環(huán)境中時(shí),可需要自己在管理線(xiàn)程的同步問(wèn)題。
LinkedList: LinkedList不同于前面兩種List,它不是基于數組的,所以不受數組性能的限制。
它每一個(gè)節點(diǎn)(Node)都包含兩方面的內容:
1.節點(diǎn)本身的數據(data);
2.下一個(gè)節點(diǎn)的信息(nextNode)。
所以當對LinkedList做添加,刪除動(dòng)作的時(shí)候就不用像基于數組的ArrayList一樣,必須進(jìn)行大量的數據移動(dòng)。只要更改nextNode的相關(guān)信息就可以實(shí)現了,這是LinkedList的優(yōu)勢。
List總結: - 所有的List中只能容納單個(gè)不同類(lèi)型的對象組成的表,而不是Key-Value鍵值對。例如:[ tom,1,c ]
- 所有的List中可以有相同的元素,例如Vector中可以有 [ tom,koo,too,koo ]
- 所有的List中可以有null元素,例如[ tom,null,1 ]
- 基于A(yíng)rray的List(Vector,ArrayList)適合查詢(xún),而LinkedList 適合添加,刪除操作
--------------------------------------NB分割線(xiàn)------------------------------------
Set: Set是一種不包含重復的元素的無(wú)序Collection。
HashSet: 雖然Set同List都實(shí)現了Collection接口,但是他們的實(shí)現方式卻大不一樣。List基本上都是以Array為基礎。但是Set則是在 HashMap的基礎上來(lái)實(shí)現的,這個(gè)就是Set和List的根本區別。HashSet的存儲方式是把HashMap中的Key作為Set的對應存儲項??纯?HashSet的add(Object obj)方法的實(shí)現就可以一目了然了。
- public boolean add(Object obj) {
- return map.put(obj, PRESENT) == null;
- }
public boolean add(Object obj) {return map.put(obj, PRESENT) == null;}這個(gè)也是為什么在Set中不能像在List中一樣有重復的項的根本原因,因為HashMap的key是不能有重復的。
LinkedHashSet: HashSet的一個(gè)子類(lèi),一個(gè)鏈表。
TreeSet: SortedSet的子類(lèi),它不同于HashSet的根本就是TreeSet是有序的。它是通過(guò)SortedMap來(lái)實(shí)現的。
Set總結: - Set實(shí)現的基礎是Map(HashMap)
- Set中的元素是不能重復的,如果使用add(Object obj)方法添加已經(jīng)存在的對象,則會(huì )覆蓋前面的對象
--------------------------------------2B分割線(xiàn)------------------------------------
Map: Map 是一種把鍵對象和值對象進(jìn)行關(guān)聯(lián)的容器,而一個(gè)值對象又可以是一個(gè)Map,依次類(lèi)推,這樣就可形成一個(gè)多級映射。對于鍵對象來(lái)說(shuō),像Set一樣,一個(gè) Map容器中的鍵對象不允許重復,這是為了保持查找結果的一致性;如果有兩個(gè)鍵對象一樣,那你想得到那個(gè)鍵對象所對應的值對象時(shí)就有問(wèn)題了,可能你得到的并不是你想的那個(gè)值對象,結果會(huì )造成混亂,所以鍵的唯一性很重要,也是符合集合的性質(zhì)的。當然在使用過(guò)程中,某個(gè)鍵所對應的值對象可能會(huì )發(fā)生變化,這時(shí)會(huì )按照最后一次修改的值對象與鍵對應。對于值對象則沒(méi)有唯一性的要求,你可以將任意多個(gè)鍵都映射到一個(gè)值對象上,這不會(huì )發(fā)生任何問(wèn)題(不過(guò)對你的使用卻可能會(huì )造成不便,你不知道你得到的到底是那一個(gè)鍵所對應的值對象)。
Map有兩種比較常用的實(shí)現:HashMap和TreeMap。
HashMap也用到了哈希碼的算法,以便快速查找一個(gè)鍵,
TreeMap則是對鍵按序存放,因此它便有一些擴展的方法,比如firstKey(),lastKey()等,你還可以從TreeMap中指定一個(gè)范圍以取得其子Map。
鍵和值的關(guān)聯(lián)很簡(jiǎn)單,用put(Object key,Object value)方法即可將一個(gè)鍵與一個(gè)值對象相關(guān)聯(lián)。用get(Object key)可得到與此key對象所對應的值對象。
--------------------------------------JB分割線(xiàn)------------------------------------
其它: 一、幾個(gè)常用類(lèi)的區別
1.ArrayList: 元素單個(gè),效率高,多用于查詢(xún)
2.Vector: 元素單個(gè),線(xiàn)程安全,多用于查詢(xún)
3.LinkedList:元素單個(gè),多用于插入和刪除
4.HashMap: 元素成對,元素可為空
5.HashTable: 元素成對,線(xiàn)程安全,元素不可為空
二、Vector、ArrayList和LinkedList
大多數情況下,從性能上來(lái)說(shuō)ArrayList最好,但是當集合內的元素需要頻繁插入、刪除時(shí)LinkedList會(huì )有比較好的表現,但是它們三個(gè)性能都比不上數組,另外Vector是線(xiàn)程同步的。所以:
如果能用數組的時(shí)候(元素類(lèi)型固定,數組長(cháng)度固定),請盡量使用數組來(lái)代替List;
如果沒(méi)有頻繁的刪除插入操作,又不用考慮多線(xiàn)程問(wèn)題,優(yōu)先選擇ArrayList;
如果在多線(xiàn)程條件下使用,可以考慮Vector;
如果需要頻繁地刪除插入,LinkedList就有了用武之地;
如果你什么都不知道,用ArrayList沒(méi)錯。
三、Collections和Arrays
在 Java集合類(lèi)框架里有兩個(gè)類(lèi)叫做Collections(注意,不是Collection?。┖虯rrays,這是JCF里面功能強大的工具,但初學(xué)者往往會(huì )忽視。按JCF文檔的說(shuō)法,這兩個(gè)類(lèi)提供了封裝器實(shí)現(Wrapper Implementations)、數據結構算法和數組相關(guān)的應用。
想必大家不會(huì )忘記上面談到的“折半查找”、“排序”等經(jīng)典算法吧,Collections類(lèi)提供了豐富的靜態(tài)方法幫助我們輕松完成這些在數據結構課上煩人的工作:
binarySearch:折半查找。
sort:排序,這里是一種類(lèi)似于快速排序的方法,效率仍然是O(n * log n),但卻是一種穩定的排序方法。
reverse:將線(xiàn)性表進(jìn)行逆序操作,這個(gè)可是從前數據結構的經(jīng)典考題哦!
rotate:以某個(gè)元素為軸心將線(xiàn)性表“旋轉”。
swap:交換一個(gè)線(xiàn)性表中兩個(gè)元素的位置。
……
Collections還有一個(gè)重要功能就是“封裝器”(Wrapper),它提供了一些方法可以把一個(gè)集合轉換成一個(gè)特殊的集合,如下:
unmodifiableXXX:轉換成只讀集合,這里XXX代表六種基本集合接口:Collection、List、Map、Set、SortedMap和SortedSet。如果你對只讀集合進(jìn)行插入刪除操作,將會(huì )拋出UnsupportedOperationException異常。
synchronizedXXX:轉換成同步集合。
singleton:創(chuàng )建一個(gè)僅有一個(gè)元素的集合,這里singleton生成的是單元素Set,
singletonList和singletonMap分別生成單元素的List和Map。
空集:由Collections的靜態(tài)屬性EMPTY_SET、EMPTY_LIST和EMPTY_MAP表示。
這次關(guān)于Java集合類(lèi)概述就到這里,下一次我們來(lái)講解Java集合類(lèi)的具體應用,如List排序、刪除重復元素。