http://www.cnblogs.com/jasonHome/p/5969574.html
結(jié)合框架體系應(yīng)該最重要的是如何靈活利用三種接口,set,map,list,他們?nèi)绾伪闅v拐揭,各有什么特征撤蟆,怎么樣去處理,這是關(guān)鍵堂污,在這個基礎(chǔ)上再去掌握在什么場合用什么類型的接口家肯。比如說list和set,set是無序的一個空袋子,當(dāng)我們只需要放入取出盟猖,這個接口當(dāng)然是最實用的息楔,但是如果我們需要按序取出,這個方法就不能用了扒披,而要用到list,map接口就有個特點圃泡,它有一個特定的key值碟案,而一個key值又對應(yīng)著一個value,這個value值中就可以存入很多的東西了颇蜡,比如姓名价说,出生年月,性別等风秤,而且可以指定key取出對應(yīng)的value1钅俊(自寫)
如果涉及到堆棧,隊列等操作缤弦,應(yīng)該考慮用List领迈,對于需要快速插入,刪除元素,應(yīng)該使用LinkedList,如果需要快速隨機訪問元素攻人,應(yīng)該使用ArrayList丰泊。
如果程序在單線程環(huán)境中,或者訪問僅僅在一個線程中進(jìn)行询一,考慮非同步的類,其效率較高,如果多個線程可能同時操作一個類朽褪,應(yīng)該使用同步的類置吓。
要特別注意對哈希表的操作,作為key的對象要正確復(fù)寫equals和hashCode方法缔赠。
盡量返回接口而非實際的類型衍锚,如返回List而非ArrayList,這樣如果以后需要將ArrayList換成LinkedList時橡淑,客戶端代碼不用改變构拳。這就是針對抽象編程。
一梁棠、系統(tǒng)簡述:
Java中集合類定義主要是Java.util.*包下面置森,常用的集合在系統(tǒng)中定義了三大接口,這三類的區(qū)別是:
java.util.Set接口及其子類符糊,set提供的是一個無序的集合凫海;
java.util.List接口及其子類,List提供的是一個有序的集合男娄;
java.util.Map接口及其子類行贪,Map提供了一個映射(對應(yīng))關(guān)系的集合數(shù)據(jù)結(jié)構(gòu);
另外模闲,在JDK5中新增了Queue(隊列)接口及其子類建瘫,提供了基于隊列的集合體系。每種集合尸折,都可以理解為用來在內(nèi)存中存放一組對象的某種”容器“---就像數(shù)組啰脚,就像前面我們自己定義的隊列。
Set 是最簡單的一種集合实夹,它的對象不按特定方式排序橄浓,只是簡單的把對象加入集合中,就像往口袋里放東西亮航。對集中成員的訪問和操作是通過集中對象的引用進(jìn)行的荸实,所以集中不能有重復(fù)對象;而LIst的主要特征是其對象以線性方式存儲缴淋,沒有特定順序准给,只有一個開頭和一個結(jié)尾,當(dāng)然宴猾,它與根本沒有順序的集是不同的圆存。列表在數(shù)據(jù)結(jié)構(gòu)中分別表現(xiàn)為:數(shù)組和向量、鏈表仇哆、堆棧沦辙、隊列。關(guān)于實現(xiàn)列表的集合類讹剔,是我們?nèi)粘9ぷ髦薪?jīng)常用到的油讯;從類圖中可以看到详民,Set?和List都是繼承了Collection接口的子接口,而這類集合都有自己的實現(xiàn)陌兑;
現(xiàn)實生活中沈跨,我們常會看到這樣的一種集合:IP地址與主機名,身份證號與個人兔综,系統(tǒng)用戶用與系統(tǒng)用戶對象等饿凛,這種一一對應(yīng)的關(guān)系,就叫做映射软驰。Java提供了專門的集合類用來存放這種對象關(guān)系的對象涧窒,即java.util.Map接口。Map是一個接口锭亏,有多種具體的實現(xiàn)類纠吴,常用的有HashMap和 Hashtable類實現(xiàn)。Map中存入的對象是一對一對的慧瘤,即每個對象和它的一個名字(鍵)關(guān)聯(lián)在一起戴已,Map中數(shù)據(jù)存放的結(jié)構(gòu)如下圖示:
Key(鍵或名)
Value(key對應(yīng)的值)
“userName1”
UserInfo對象1
“userName1”
UserInfo對象1
“userName1”
UserInfo對象1
.?.?.
.?.?.
可以看出,Map中存放的是兩種對象锅减,一種稱為key(鍵)糖儡,一種稱為value(值),它們在在Map中是一一對應(yīng)關(guān)系怔匣,這一對對象又稱做Map中的一個Entry(項)休玩;Map中的鍵不能重復(fù),但值可以重復(fù)劫狠。(借鑒藍(lán)杰,>>>)
二永部、詳細(xì)闡述:
一独泞、概述
數(shù)據(jù)結(jié)構(gòu)對程序設(shè)計有著深遠(yuǎn)的影響,在面向過程的C語言中苔埋,數(shù)據(jù)庫結(jié)構(gòu)用struct來描述懦砂,而在面向?qū)ο蟮木幊讨校瑪?shù)據(jù)結(jié)構(gòu)是用類來描述的组橄,并且包含有對該數(shù)據(jù)結(jié)構(gòu)操作的方法荞膘。
在Java語言中,Java語言的設(shè)計者對常用的數(shù)據(jù)結(jié)構(gòu)和算法做了一些規(guī)范(接口)和實現(xiàn)(具體實現(xiàn)接口的類)玉工。所有抽象出來的數(shù)據(jù)結(jié)構(gòu)和操作(算法)統(tǒng)稱為Java集合框架(Java?Collection?Framework)羽资。
Java程序員在具體應(yīng)用時,不必考慮數(shù)據(jù)結(jié)構(gòu)和算法實現(xiàn)細(xì)節(jié)遵班,只需要用這些類創(chuàng)建出來一些對象屠升,然后直接應(yīng)用就可以了潮改。這樣就大大提高了編程效率。
二腹暖、集合框架的層次結(jié)構(gòu)
Collection是集合接口
|――――Set子接口:無序汇在,不允許重復(fù)。
|――――List子接口:有序脏答,可以有重復(fù)元素糕殉。
區(qū)別:Collections是集合類
Set和List對比:
Set:檢索元素效率低下,刪除和插入效率高殖告,插入和刪除不會引起元素位置改變阿蝶。
List:和數(shù)組類似,List可以動態(tài)增長丛肮,查找元素效率高赡磅,插入刪除元素效率低,因為會引起其他元素位置改變宝与。
Set和List具體子類:
Set
|――――HashSet:以哈希表的形式存放元素焚廊,插入刪除速度很快。
List
|――――ArrayList:動態(tài)數(shù)組
|――――LinkedList:鏈表习劫、隊列咆瘟、堆棧。
Array和java.util.Vector
Vector是一種老的動態(tài)數(shù)組诽里,是線程同步的袒餐,效率很低,一般不贊成使用谤狡。
三灸眼、Iterator迭代器(接口)
Iterator是獲取集合中元素的過程,實際上幫助獲取集合中的元素墓懂。
迭代器代替了?Java?Collections?Framework?中的?Enumeration焰宣。迭代器與枚舉有兩點不同:
迭代器允許調(diào)用方利用定義良好的語義在迭代期間從迭代器所指向的集合移除元素。
方法名稱得到了改進(jìn)捕仔。
Iterator 僅有一個子接口ListIterator匕积,是列表迭代器,允許程序員按任一方向遍歷列表榜跌、迭代期間修改列表闪唆,并獲得迭代器在列表中的當(dāng)前位置。 ListIterator?沒有當(dāng)前元素钓葫;它的光標(biāo)位置?始終位于調(diào)用?previous()?所返回的元素和調(diào)用?next()?所返回的元素之間悄蕾。在長度為?n?的列表中,有?n+1?個有效的索引值础浮,從?0?到?n(包含)笼吟。
四库物、集合框架之外的Map接口
Map將鍵映射到值的對象。一個映射不能包含重復(fù)的鍵贷帮;每個鍵最多只能映射一個值戚揭。
Map接口是Dictionary(字典)抽象類的替代品。
Map?接口提供三種collection?視圖撵枢,允許以鍵集民晒、值集合或鍵-值映射關(guān)系集的形式查看某個映射的內(nèi)容。映射的順序?定義為迭代器在映射的?collection?視圖中返回其元素的順序锄禽。某些映射實現(xiàn)可明確保證其順序潜必,如?TreeMap?類;某些映射實現(xiàn)則不保證順序沃但,如?HashMap?類磁滚。
有兩個常見的已實現(xiàn)的子類:
HashMap:基于哈希表的?Map?接口的實現(xiàn)。此實現(xiàn)提供所有可選的映射操作宵晚,并允許使用?null?值和?null?鍵垂攘。(除了不同步和允許使用?null?之外,HashMap?類與?Hashtable?大致相同淤刃。)此類不保證映射的順序晒他,特別是它不保證該順序恒久不變。
TreeMap:它實現(xiàn)SortedMap?接口的基于紅黑樹的實現(xiàn)逸贾。此類保證了映射按照升序順序排列關(guān)鍵字陨仅,根據(jù)使用的構(gòu)造方法不同,可能會按照鍵的類的自然順序?進(jìn)行排序(參見?Comparable)铝侵,或者按照創(chuàng)建時所提供的比較器進(jìn)行排序灼伤。
Hashtable:此類實現(xiàn)一個哈希表,該哈希表將鍵映射到相應(yīng)的值咪鲜。任何非?null?對象都可以用作鍵或值饺蔑。
五、線程安全類
在集合框架中嗜诀,有些類是線程安全的,這些都是JDK1.1中的出現(xiàn)的孔祸。在JDK1.2之后隆敢,就出現(xiàn)許許多多非線程安全的類。
下面是這些線程安全的同步的類:
Vector:就比ArrayList多了個同步化機制(線程安全)崔慧。
Statck:堆棧類拂蝎,先進(jìn)后出。
Hashtable:就比HashMap多了個線程安全惶室。
Enumeration:枚舉温自,相當(dāng)于迭代器玄货。
除了這些之外,其他的都是非線程安全的類和接口悼泌。
線程安全的類其方法是同步的松捉,每次只能一個訪問。是重量級對象馆里,效率較低隘世。對于非線程安全的類和接口,在多線程中需要程序員自己處理線程安全問題鸠踪。
六丙者、其他一些接口和類介紹
Dictionary和Hashtable類:
Dictionary提供鍵值映射的功能,是個抽象類营密。一般使用它的子類HashTable類械媒。遍歷Hashtable類要用到枚舉。
Properties類
Properties?繼承于?Hashtable评汰,Properties?類表示了一個持久的屬性集纷捞。Properties?可保存在流中或從流中加載。屬性列表中每個鍵及其對應(yīng)值都是一個字符串键俱。一般可以通過讀取properties配置文件來填充Properties對象兰绣。
七、各個接口的闡述
1.Collection接口
Collection是最基本的集合接口编振,一個Collection代表一組Object缀辩,即Collection的元素(Elements)。一些 Collection允許相同的元素而另一些不行踪央。一些能排序而另一些不行臀玄。Java?SDK不提供直接繼承自Collection的類,Java?SDK提供的類都是繼承自Collection的“子接口”如List和Set畅蹂。
所有實現(xiàn)Collection接口的類都必須提供兩個標(biāo)準(zhǔn)的構(gòu)造函數(shù):無參數(shù)的構(gòu)造函數(shù)用于創(chuàng)建一個空的Collection健无,有一個 Collection參數(shù)的構(gòu)造函數(shù)用于創(chuàng)建一個新的Collection,這個新的Collection與傳入的Collection有相同的元素液斜。后一個構(gòu)造函數(shù)允許用戶復(fù)制一個Collection累贤。
如何遍歷Collection中的每一個元素?不論Collection的實際類型如何少漆,它都支持一個iterator()的方法臼膏,該方法返回一個迭代子,使用該迭代子即可逐一訪問Collection中每一個元素示损。典型的用法如下:
Iterator?it?=?collection.iterator();?//?獲得一個迭代子
while(it.hasNext())?{
Object?obj?=?it.next();?//?得到下一個元素
}
由Collection接口派生的兩個接口是List和Set渗磅。
2.List接口
List是有序的Collection,使用此接口能夠精確的控制每個元素插入的位置。用戶能夠使用索引(元素在List中的位置始鱼,類似于數(shù)組下標(biāo))來訪問List中的元素仔掸,這類似于Java的數(shù)組。
和下面要提到的Set不同医清,List允許有相同的元素起暮。
除了具有Collection接口必備的iterator()方法外,List還提供一個listIterator()方法状勤,返回一個 ListIterator接口鞋怀,和標(biāo)準(zhǔn)的Iterator接口相比,ListIterator多了一些add()之類的方法持搜,允許添加密似,刪除,設(shè)定元素葫盼,還能向前或向后遍歷残腌。
實現(xiàn)List接口的常用類有LinkedList,ArrayList贫导,Vector和Stack抛猫。
3.LinkedList類
LinkedList實現(xiàn)了List接口,允許null元素孩灯。此外LinkedList提供額外的get闺金,remove,insert方法在 LinkedList的首部或尾部峰档。這些操作使LinkedList可被用作堆棧(stack)败匹,隊列(queue)或雙向隊列(deque)。
注意LinkedList沒有同步方法讥巡。如果多個線程同時訪問一個List掀亩,則必須自己實現(xiàn)訪問同步。一種解決方法是在創(chuàng)建List時構(gòu)造一個同步的List:
List?list?=?Collections.synchronizedList(new?LinkedList(...));
4.ArrayList類
ArrayList實現(xiàn)了可變大小的數(shù)組欢顷。它允許所有元素槽棍,包括null。ArrayList沒有同步抬驴。
size炼七,isEmpty,get布持,set方法運行時間為常數(shù)豌拙。但是add方法開銷為分?jǐn)偟某?shù),添加n個元素需要O(n)的時間鳖链。其他的方法運行時間為線性。
每個ArrayList實例都有一個容量(Capacity),即用于存儲元素的數(shù)組的大小芙委。這個容量可隨著不斷添加新元素而自動增加逞敷,但是增長算法并沒有定義。當(dāng)需要插入大量元素時灌侣,在插入前可以調(diào)用ensureCapacity方法來增加ArrayList的容量以提高插入效率推捐。
和LinkedList一樣,ArrayList也是非同步的(unsynchronized)侧啼。
5.Vector類
Vector非常類似ArrayList牛柒,但是Vector是同步的。由Vector創(chuàng)建的Iterator痊乾,雖然和ArrayList創(chuàng)建的 Iterator是同一接口皮壁,但是,因為Vector是同步的哪审,當(dāng)一個Iterator被創(chuàng)建而且正在被使用蛾魄,另一個線程改變了Vector的狀態(tài)(例如,添加或刪除了一些元素)湿滓,這時調(diào)用Iterator的方法時將拋出ConcurrentModificationException滴须,因此必須捕獲該異常。
6.Stack?類
Stack繼承自Vector叽奥,實現(xiàn)一個后進(jìn)先出的堆棧扔水。Stack提供5個額外的方法使得Vector得以被當(dāng)作堆棧使用〕ィ基本的push和pop方法魔市,還有peek方法得到棧頂?shù)脑兀琫mpty方法測試堆棧是否為空膀篮,search方法檢測一個元素在堆棧中的位置嘹狞。Stack剛創(chuàng)建后是空棧。
7.Set接口
Set是一種不包含重復(fù)的元素的Collection誓竿,即任意的兩個元素e1和e2都有e1.equals(e2)=false磅网,Set最多有一個null元素。
很明顯筷屡,Set的構(gòu)造函數(shù)有一個約束條件涧偷,傳入的Collection參數(shù)不能包含重復(fù)的元素。
請注意:必須小心操作可變對象(Mutable?Object)毙死。如果一個Set中的可變元素改變了自身狀態(tài)導(dǎo)致Object.equals(Object)=true將導(dǎo)致一些問題燎潮。
8.Map接口
請注意,Map沒有繼承Collection接口扼倘,Map提供key到value的映射确封。一個Map中不能包含相同的key除呵,每個key只能映射一個 value。Map接口提供3種集合的視圖爪喘,Map的內(nèi)容可以被當(dāng)作一組key集合颜曾,一組value集合,或者一組key-value映射秉剑。
9.Hashtable類
Hashtable繼承Map接口泛豪,實現(xiàn)一個key-value映射的哈希表。任何非空(non-null)的對象都可作為key或者value侦鹏。
添加數(shù)據(jù)使用put(key,?value)诡曙,取出數(shù)據(jù)使用get(key),這兩個基本操作的時間開銷為常數(shù)略水。
Hashtable 通過initial?capacity和load?factor兩個參數(shù)調(diào)整性能价卤。通常缺省的load?factor?0.75較好地實現(xiàn)了時間和空間的均衡。增大load?factor可以節(jié)省空間但相應(yīng)的查找時間將增大聚请,這會影響像get和put這樣的操作荠雕。
使用Hashtable的簡單示例如下,將1驶赏,2炸卑,3放到Hashtable中,他們的key分別是”one”煤傍,”two”盖文,”three”:
Hashtable?numbers?=?new?Hashtable();
numbers.put(“one”,?new?Integer(1));
numbers.put(“two”,?new?Integer(2));
numbers.put(“three”,?new?Integer(3));
要取出一個數(shù),比如2蚯姆,用相應(yīng)的key:
Integer?n?=?(Integer)numbers.get(“two”);
System.out.println(“two?=?”?+?n);
由于作為key的對象將通過計算其散列函數(shù)來確定與之對應(yīng)的value的位置五续,因此任何作為key的對象都必須實現(xiàn)hashCode和equals方法。hashCode和equals方法繼承自根類Object龄恋,如果你用自定義的類當(dāng)作key的話疙驾,要相當(dāng)小心,按照散列函數(shù)的定義郭毕,如果兩個對象相同它碎,即obj1.equals(obj2)=true,則它們的hashCode必須相同显押,但如果兩個對象不同扳肛,則它們的hashCode不一定不同,如果兩個不同對象的hashCode相同乘碑,這種現(xiàn)象稱為沖突挖息,沖突會導(dǎo)致操作哈希表的時間開銷增大,所以盡量定義好的hashCode()方法兽肤,能加快哈希表的操作套腹。
如果相同的對象有不同的hashCode绪抛,對哈希表的操作會出現(xiàn)意想不到的結(jié)果(期待的get方法返回null),要避免這種問題电禀,只需要牢記一條:要同時復(fù)寫equals方法和hashCode方法睦疫,而不要只寫其中一個。
結(jié)合框架體系應(yīng)該最重要的是如何靈活利用三種接口鞭呕,set,map,list,他們?nèi)绾伪闅v,各有什么特征宛官,怎么樣去處理葫松,這是關(guān)鍵,在這個基礎(chǔ)上再去掌握在什么場合用什么類型的接口底洗。比如說list和set,set是無序的一個空袋子腋么,當(dāng)我們只需要放入取出,這個接口當(dāng)然是最實用的亥揖,但是如果我們需要按序取出珊擂,這個方法就不能用了,而要用到list,map接口就有個特點费变,它有一個特定的key值摧扇,而一個key值又對應(yīng)著一個value,這個value值中就可以存入很多的東西了挚歧,比如姓名扛稽,出生年月,性別等滑负,而且可以指定key取出對應(yīng)的valueT谡拧(自寫)
如果涉及到堆棧,隊列等操作矮慕,應(yīng)該考慮用List帮匾,對于需要快速插入,刪除元素痴鳄,應(yīng)該使用LinkedList瘟斜,如果需要快速隨機訪問元素,應(yīng)該使用ArrayList夏跷。
如果程序在單線程環(huán)境中哼转,或者訪問僅僅在一個線程中進(jìn)行,考慮非同步的類槽华,其效率較高壹蔓,如果多個線程可能同時操作一個類,應(yīng)該使用同步的類猫态。
要特別注意對哈希表的操作佣蓉,作為key的對象要正確復(fù)寫equals和hashCode方法披摄。
盡量返回接口而非實際的類型,如返回List而非ArrayList勇凭,這樣如果以后需要將ArrayList換成LinkedList時疚膊,客戶端代碼不用改變。這就是針對抽象編程虾标。