終于下定決心看源碼了垫卤,看了一天自己都是懵逼狀態(tài)的威彰。既然懵逼了,那就從頭開始穴肘,從最基礎的開始歇盼,遇到的問題解決了再繼續(xù),不管多簡單评抚,都要學習記錄豹缀。
Java中集合的知識
1.List知識:有序的并且數(shù)據(jù)可以重復的集合
List包括List接口以及List接口的所有實現(xiàn)類。因為List接口實現(xiàn)了Collection接口慨代,所以List接口擁有Collection接口提供的所有常用方法邢笙,又因為List是列表類型,所以List接口還提供了一些適合于自身的常用方法鱼响。
sublist(int fromindex鸣剪,int toIndex )方法截取現(xiàn)有List集合中的部分對象生成新的List集合時,需要注意的是,新生成的集合中包含起始索引位置代表的對象筐骇,但是不包含終止索引位置代表的對象
List接口提供的適合于自身的常用方法均與索引有關债鸡,這是因為List集合為列表類型,以線性方式存儲對象铛纬,可以通過對象的索引操作對象厌均。
List接口的常用實現(xiàn)類有ArrayList和LinkedList,在使用List集合時告唆,通常情況下聲明為List類型棺弊,實例化時根據(jù)實際情況的需要,實例化為ArrayList或LinkedList擒悬,例如:
List l = newArrayList();// 利用ArrayList類實例化List集合
List l2 = newLinkedList();// 利用LinkedList類實例化List集合
2.Map的知識:以按鍵/數(shù)值對的形式存儲數(shù)據(jù)模她,和數(shù)組非常相似,在數(shù)組中存在的索引懂牧,它們本身也是對象侈净。
Map是一種把鍵對象和值對象進行關聯(lián)的容器,而一個值對象又可以是一個Map僧凤,依次類推畜侦,這樣就可形成一個多級映射。對于鍵對象來說躯保,像Set一樣旋膳,一個Map容器中的鍵對象不允許重復,這是為了保持查找結果的一致性;如果有兩個鍵對象一樣途事,那你想得到那個鍵對象所對應的值對象時就有問題了验懊,可能你得到的并不是你想的那個值對象,結果會造成混亂盯孙,所以鍵的唯一性很重要鲁森,也是符合集合的性質的祟滴。當然在使用過程中振惰,某個鍵所對應的值對象可能會發(fā)生變化,這時會按照最后一次修改的值對象與鍵對應垄懂。對于值對象則沒有唯一性的要求骑晶。你可以將任意多個鍵都映射到一個值對象上,這不會發(fā)生任何問題(不過對你的使用卻可能會造成不便草慧,你不知道你得到的到底是那一個鍵所對應的值對象)桶蛔。
Java核心類中有很多預定義的Map?類。在介紹具體實現(xiàn)之前漫谷,我們先介紹一下Map?接口本身仔雷,以便了解所有實現(xiàn)的共同點。Map?接口定義了四種類型的方法,每個Map?都包含這些法碟婆。
插入和刪除元素的方法
返回視圖的Map 方法:使用這些方法返回的對象电抚,您可以遍歷Map 的元素,還可以刪除Map 中的元素竖共。
Map?通常適合按鍵(而非按值)進行訪問蝙叛。Map?定義中沒有規(guī)定這肯定是真的,但通常您可以期望這是真的公给。例如借帘,您可以期望containsKey()方法與get()?方法一樣快。另一面淌铐,containsValue()?方法很可能需要掃描?Map?中的值肺然,因此它的速度可能比較慢。這些方法檢索有關Map內容的信息但不更改Map內容腿准。
Map有兩種比較常用的實現(xiàn):HashMap和TreeMap狰挡。HashMap也用到了哈希碼的算法,以便快速查找一個鍵释涛,TreeMap則是對鍵按序存放加叁,因此它便有一些擴展的方法,比如firstKey(),lastKey()等唇撬,你還可以從TreeMap中指定一個范圍以取得其子Map它匕。鍵和值的關聯(lián)很簡單,用pub(Object key,Objectvalue)方法即可將一個鍵與一個值對象相關聯(lián)窖认。用get(Objectkey)可得到與此key對象所對應的值對象豫柬。
Hashtable繼承Map接口,實現(xiàn)一個key-value映射的哈希表扑浸。任何非空(non-null)的對象都可作為key或者value烧给。?添加數(shù)據(jù)使用put(key, value),取出數(shù)據(jù)使用get(key)喝噪,這兩個基本操作的時間開銷為常數(shù)础嫡。
HashMap和Hashtable類似,不同之處在于HashMap是非同步的酝惧,并且允許null榴鼎,即null value和null key。晚唇,但是將HashMap視為Collection時(values()方法可返回Collection)巫财,其迭代子操作時間開銷和HashMap的容量成比例。因此哩陕,如果迭代操作的性能相當重要的話平项,不要將HashMap的初始化容量設得過高赫舒,或者load factor過低。
WeakHashMap類
WeakHashMap是一種改進的HashMap闽瓢,它對key實行“弱引用”号阿,如果一個key不再被外部所引用,那么該key可以被GC回收鸳粉。
Hashtable類和HashMap類的區(qū)別:Hashtable和HashMap類有三個重要的不同之處扔涧。
第一個不同主要是歷史原因。Hashtable是基于陳舊的Dictionary類的届谈,HashMap是Java 1.2引進的Map接口的一個實現(xiàn)枯夜。
也許最重要的不同是Hashtable的方法是同步的,而HashMap的方法不是艰山。這就意味著湖雹,雖然你可以不用采取任何特殊的行為就可以在一個多線程的應用程序中用一個Hashtable,但你必須同樣地為一個HashMap提供外同步曙搬。一個方便的方法就是利用Collections類的靜態(tài)的synchronizedMap()方法摔吏,它創(chuàng)建一個線程安全的Map對象,并把它作為一個封裝的對象來返回纵装。這個對象的方法可以讓你同步訪問潛在的HashMap征讲。這么做的結果就是當你不需要同步時,你不能切斷Hashtable中的同步(比如在一個單線程的應用程序中)橡娄,而且同步增加了很多處理費用诗箍。
第三點不同是,只有HashMap可以讓你將空值作為一個表的條目的key或value挽唉。HashMap中只有一條記錄可以是一個空的key滤祖,但任意數(shù)量的條目可以是空的value。這就是說瓶籽,如果在表中沒有發(fā)現(xiàn)搜索鍵匠童,或者如果發(fā)現(xiàn)了搜索鍵,但它是一個空的值塑顺,那么get()將返回null汤求。如果有必要,用containKey()方法來區(qū)別這兩種情況茬暇。
3.set的知識:Set具有與Collection完全一樣的接口首昔,因此沒有任何額外的功能寡喝。實際上Set就是Collection糙俗,只是行為不同。
實現(xiàn)了Set接口的主要有HashSet预鬓、TreeSet巧骚、LinkedHashSet這幾個共同點就是每個相同的項只保存一份赊颠。他們也有不同點,區(qū)別如下:
1.HashSet:HashSet使用的是相當復雜的方式來存儲元素的劈彪,使用HashSet能夠最快的獲取集合中的元素竣蹦,效率非常高(以空間換時間)。會根據(jù)hashcode和equals來龐端是否是同一個對象沧奴,如果hashcode一樣痘括,并且equals返回true,則是同一個對象滔吠,不能重復存放纲菌。
2.TreeSet:TreeSet也不能存放重復對象,但是TreeSet會自動排序疮绷,如果存放的對象不能排序則會報錯翰舌,所以存放的對象必須指定排序規(guī)則。排序規(guī)則包括自然排序和客戶排序冬骚。
①自然排序:TreeSet要添加哪個對象就在哪個對象類上面實現(xiàn)java.lang.Comparable接口椅贱,并且重寫comparaTo()方法,返回0則表示是同一個對象只冻,否則為不同對象庇麦。
②客戶排序:建立一個第三方類并實現(xiàn)java.util.Comparator接口。并重寫方法喜德。定義集合形式為TreeSet ts = new TreeSet(new 第三方類());
3.LinkedHashSet:LinkedHashSet按照插入順序保存對象女器,同時還保存了HashSet的查詢速度。
總結
1.?如果涉及到堆棧住诸,隊列等操作驾胆,應該考慮用List,對于需要快速插入贱呐,刪除元素丧诺,應該使用LinkedList,如果需要快速隨機訪問元素奄薇,應該使用ArrayList驳阎。
2. 如果程序在單線程環(huán)境中,或者訪問僅僅在一個線程中進行馁蒂,考慮非同步的類呵晚,其效率較高,如果多個線程可能同時操作一個類沫屡,應該使用同步的類饵隙。
3. 在除需要排序時使用TreeSet,TreeMap外,都應使用HashSet,HashMap,因為他們 的效率更高。
4. 要特別注意對哈希表的操作沮脖,作為key的對象要正確復寫equals和hashCode方法金矛。
5. 容器類僅能持有對象引用(指向對象的指針)芯急,而不是將對象信息copy一份至數(shù)列某位置。一旦將對象置入容器內驶俊,便損失了該對象的型別信息娶耍。
6. 盡量返回接口而非實際的類型,如返回List而非ArrayList饼酿,這樣如果以后需要將ArrayList換成LinkedList時榕酒,客戶端代碼不用改變。這就是針對抽象編程故俐。
注意:
1奈应、Collection沒有get()方法來取得某個元素。只能通過iterator()遍歷元素购披。
2杖挣、Set和Collection擁有一模一樣的接口。
3刚陡、List惩妇,可以通過get()方法來一次取出一個元素。使用數(shù)字來選擇一堆對象中的一個筐乳,get(0)...歌殃。(add/get)
4、一般使用ArrayList蝙云。用LinkedList構造堆棧stack氓皱、隊列queue。
5勃刨、Map用 put(k,v) / get(k)波材,還可以使用containsKey()/containsValue()來檢查其中是否含有某個key/value。
HashMap會利用對象的hashCode來快速找到key身隐。
6廷区、Map中元素,可以將key序列贾铝、value序列單獨抽取出來隙轻。
使用keySet()抽取key序列,將map中的所有keys生成一個Set垢揩。
使用values()抽取value序列玖绿,將map中的所有values生成一個Collection。
為什么一個生成Set叁巨,一個生成Collection斑匪?那是因為,key總是獨一無二的俘种,value允許重復秤标。