Java集合Collection、List、Set、Map使用詳解文檔_第1頁
Java集合Collection、List、Set、Map使用詳解文檔_第2頁
Java集合Collection、List、Set、Map使用詳解文檔_第3頁
Java集合Collection、List、Set、Map使用詳解文檔_第4頁
Java集合Collection、List、Set、Map使用詳解文檔_第5頁
已閱讀5頁,還剩41頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

1、優(yōu)質(zhì)文檔Java集合排序及java集合類詳解(Co I Iect i on, L i st, Set, Map)摘要內(nèi)容集合是Java里面最常用的,也是最重要的一部分。.能夠用好集合 和理解好集合對于做Java程序的開發(fā)擁有無比的好處。本文詳細(xì)解釋 了關(guān)于Java中的集合是如何實現(xiàn)的,以及他們的實現(xiàn)原理。目錄TOCol-3lizu 1 集合框架11.1 集合框架概述2111容器簡介21.1.2 容器的分類41.2 Collection61.2.1 常用方法61.2.2 迭代器81.3 List111.3.1 概述111.3.2 常用方法111.3.3 實現(xiàn)原理151.4 Map181.4.1

2、概述181.4.2 常用方法181.4.3 Comparable接口 241.4.4 實現(xiàn)原理251.4.5 覆寫 hashCode()291.5 Set341.5.1 概述341.5.2 常用方法341.5.3 實現(xiàn)原理391.6 總結(jié):集合框架中常用類比較392 練習(xí)403 附錄:排序421 集合框架1.1 集合框架概述1.1.1 容器簡介到目前為止,我們已經(jīng)學(xué)習(xí)了如何創(chuàng)建多個不同的對象,定義了這 些對象以后,我們就可以利用它們來做一些有意義的事情。.舉例來說,假設(shè)要存儲許多雇員,不同的雇員的區(qū)別僅在于雇員 的身份證號。.我們可以通過身份證號來順序存儲每個雇員,但是在內(nèi) 存中實現(xiàn)呢?是不是

3、要準(zhǔn)備足夠的內(nèi)存來存儲1000個雇員,然后再將 這些雇員逐一插入?如果已經(jīng)插入了 500條記錄,這時需要插入一個身 份證號較低的新雇員,該怎么辦呢?是在內(nèi)存中將500條記錄全部下移 后,再從開頭插入新的記錄?還是創(chuàng)建一個映射來記住每個對象的位 置?當(dāng)決定如何存儲對象的集合時.,必須考慮如下問題。對于對象集合,必須執(zhí)行的操作主要以下三種: 添加新的對象 刪除對象 查找對象我們必須確定如何將新的對象添加到集合中??梢詫ο筇砑拥郊?合的末尾、開頭或者中間的某個邏輯位置。從集合中刪除一個對象后,對象集合中現(xiàn)有對象會有什么影響呢? 可能必須將內(nèi)存移來移去,或者就在現(xiàn)有對象所駐留的內(nèi)存位置下一個 “洞”

4、。在內(nèi)存中建立對象集合后,必須確定如何定位特定對象??山?一種機制,利用該機制可根據(jù)某些搜索條件(例如身份證號)直接定位 到目標(biāo)對象;否則,便需要遍歷集合中的每個對象,直到找到要查找的 對象為止。前面大家已經(jīng)學(xué)習(xí)過了數(shù)組。數(shù)組的作用是可以存取一組數(shù)據(jù)。 但是它卻存在一些缺點,使得無法使用它來比較方便快捷的完成上述應(yīng) 用場景的要求。1. 首先,在很多數(shù)情況下面,我們需要能夠存儲一組數(shù)據(jù)的容 器,這一點雖然數(shù)組可以實現(xiàn),但是如果我們需要存儲的數(shù)據(jù) 的個數(shù)多少并不確定。比如說:我們需要在容器里面存儲某個 應(yīng)用系統(tǒng)的當(dāng)前的所有的在線用戶信息,而當(dāng)前的在線用戶信 息是時刻都可能在變化的。也就是說,我們

5、需要一種存儲數(shù) 據(jù)的容器,它能夠自動的改變這個容器的所能存放的數(shù)據(jù)數(shù)量 的大小。這一點上,如果使用數(shù)組來存儲的話,就顯得十分的 笨拙O2. 我們再假設(shè)這樣一種場景:假定一個購物網(wǎng)站,經(jīng)過一段時間的運行,我們已經(jīng)存儲了一系列的購物清單了,購物清單中 有商品信息。如果我們想要知道這段時間里面有多少種商品被 銷售出去了。那么我們就需要一個容器能夠自動的過濾掉購物 清單中的關(guān)于商品的重復(fù)信息。如果使用數(shù)組,這也是很難實 現(xiàn)的。3. 最后再想想,我們經(jīng)常會遇到這種情況,我知道某個人的帳號名稱,希望能夠進一步了解這個人的其他的一些信息。也就 是說,我們在一個地方存放一些用戶信息,我們希望能夠通過 用戶的帳

6、號來查找到對應(yīng)的該用戶的其他的一些信息。再舉個 查字典例子:假設(shè)我們希望使用一個容器來存放單詞以及對于 這個單詞的解釋,而當(dāng)我們想要查找某個單詞的意思的時候, 能夠根據(jù)提供的單詞在這個容器中找到對應(yīng)的單詞的解釋。如 果使用數(shù)組來實現(xiàn)的話,就更加的困難了。為解決這些問題,Java里面就設(shè)計了容器集合,不同的容器集合以 不同的格式保存對象。數(shù)學(xué)背景在常見用法中,集合(collection)和數(shù)學(xué)上直觀的集(set)的概 念是相同的。集是一個唯一項組,也就是說組中沒有重復(fù)項。實際上, 集合框架包含了一個Set接口和許多具體的Set類。但正式的集 概念卻比Java技術(shù)提前了一個世紀(jì),那時英國數(shù)學(xué)家Ge

7、orge Boo Ie按邏輯正式的定義了集的概念。大部分人在小學(xué)時通過我們熟悉的 維恩圖引入的集的交和集的并學(xué)到過一些集的理論。集的基本屬性如下: 集內(nèi)只包含每項的一個實例 集可以是有限的,也可以是無限的 可以定義抽象概念集不僅是邏輯學(xué)、數(shù)學(xué)和計算機科學(xué)的基礎(chǔ),對于商業(yè)和系統(tǒng)的日 常應(yīng)用來說,它也很實用。連接池這一概念就是數(shù)據(jù)庫服務(wù)器的一個 開放連接集。Web服務(wù)器必須管理客戶機和連接集。文件描述符提供 了操作系統(tǒng)中另一個集的示例。映射是一種特別的集。它是一種對(pair)集,每個對表示一個元 素到另一元素的單向映射。一些映射示例有: IP地址到域名(DNS)的映射 關(guān)鍵字到數(shù)據(jù)庫記錄的映射

8、字典(詞到含義的映射) 2進制到10進制轉(zhuǎn)換的映射就像集一樣,映射背后的思想比Java編程語言早的多,甚至比計 算機科學(xué)還早。而Java中的Map就是映射的一種表現(xiàn)形式。1.1.2 容器的分類既然您已經(jīng)具備了一些集的理論,您應(yīng)該能夠更輕松的理解集合框 架。集合框架由一組用來操作對象的接口組成。不同接口描述不同 類型的組。在很大程度上,一旦您理解了接口,您就理解了框架。雖然 您總要創(chuàng)建接口特定的實現(xiàn),但訪問實際集合的方法應(yīng)該限制在接口方 法的使用上;因此,允許您更改基本的數(shù)據(jù)結(jié)構(gòu)而不必改變其它代碼。 框架接口層次結(jié)構(gòu)如下圖所示。Java容器類類庫的用途是“保存對象”,并將其劃分為兩個不同的 概念

9、:1)Collection。 一組對立的元素,通常這些元素都服從某種規(guī)則。 List必須保持元素特定的順序,而Set不能有重復(fù)元素。2) Map o 一組成對的“鍵值對”對象。初看起來這似乎應(yīng)該是 一個Collection ,其元素是成對的對象,但是這樣的設(shè)計實現(xiàn)起 來太笨拙了,于是我們將Map明確的提取出來形成一個獨立的概 念。Map一樣容易擴展成多維Map ,無需增加新的概念,只要讓 Map中的鍵值對的每個“值”也是一個Map即可。Collection和Map的區(qū)別在于容器中每個位置保存的元素個數(shù)。Co llection每個位置只能保存一個元素(對象)。此類容器包括:List , 它以特定

10、的順序保存一組元素;Set則是元素不能重復(fù)。Map保存的是“鍵值對,就像一個小型數(shù)據(jù)庫。我們可以通過“鍵” 找到該鍵對應(yīng)的“值”。 Collection -對象之間沒有指定的順序,允許重復(fù)元素。 Set - 對象之間沒有指定的順序,不允許重復(fù)元素 List-對象之間有指定的順序,允許重復(fù)元素,并引入位置下標(biāo)。 Map - 接口用于保存關(guān)鍵字(Key)和數(shù)值(Value)的集 合,集合中的每個對象加入時都提供數(shù)值和關(guān)鍵字。Map接口 既不繼承Set也不繼承CollectionoList、Set、Map共同的實現(xiàn)基礎(chǔ)是Object數(shù)組除了四個歷史集合類外,Java 2框架還引入了六個集合實現(xiàn),如

11、下表所示。接口實現(xiàn)歷史集合類SetHashSetTreeSetListArrayListVectorLinkedListStackMapHashMapHashtableTreeMapProperties歷史集合類部分解釋Vector是個像可增大數(shù)組的歷史集合類,但它可以存儲不同類型的 數(shù)據(jù)元素。Java 2 SDK,版本2中Vector類被改良至“集合框架”層次 結(jié)構(gòu)中以實現(xiàn)List接口。但是,如果您在使用新框架,您應(yīng)該使用Arr ayList, 而不是 List。從Vector轉(zhuǎn)換為ArrayList時,一個關(guān)鍵的差別是 一為了更改元 素值的位置,參數(shù)的順序被顛倒了。Stack類繼承Vect

12、or,通過push()和pop()方法以實現(xiàn)一個標(biāo)準(zhǔn)的 后進先出(last-in-first-out (LIFO)堆棧??墒牵覀円?dāng)心。因為S tack類繼承Vector類,您仍然可以用被繼承的Vector的方法訪問或修 改 StackoEnumeration 接 口Enumeration接口允許您迭代集合中的所有元素。在“集合框架”中, 該接口被Iterator接口替代。但是,并不是所有的庫都支持較新的接口, 所以您可能會發(fā)現(xiàn)自己常常使用Enumerationo盡管有些人更喜歡Herat or這個方法名稱,但用Enumeration迭代和用Iterator迭代類似。不過, Enumerat

13、ion不支持除去操作。Enumeration enum = while (enum.hasNextElement() Object element = iterator.nextElement();/ process element Hashtable實現(xiàn)是個一般的字典,它允許存儲任何對象作為它的鍵 或值(包括null) o在Java 2 SDK,版本1.2中,這個類被重新改 寫到“集合框架”中去實現(xiàn)Map接口。所以,您可用原始的Hashtab le方法或較新的Map方法。如果您需要一個同步的Map,使用Has htable比使用同步的HashMap稍快一些。任何集合(Collection )

14、都能產(chǎn)生一個迭代器(Iterator ),而一 個List除了能生成一個Listiterator (列表迭代器)外,還能生成一個 普通迭代器,因為List正是從集合繼承來的.1.2 Collection1.2.1 常用方法Collection接口用于表示任何對象或元素組。想要盡可能以常規(guī)方式 處理一組元素時,就使用這一接口。Collection在前而的大圖也可以看出,它是 List和Set的父類。并且它本身也是一個接口。它定義了作為集合所應(yīng)該擁有的 一些方法。如下: 注意:集合必須只有對象,集合中的元素不能是基本數(shù)據(jù)類型。Collection接口支持如添加和除去等基本操作。設(shè)法除去一個元素時,

15、如果這個元素存在,除去的僅僅是集合中此元素的一個實例。 boolean add(Object element) boolean remove(Object element)Collection接口還支持查詢操作: int size() boolean isEmptyO boolean contains(Object element) Iterator iterator()組操作:Collection接口支持的其它操作,要么是作用于元素組的任務(wù), 要么是同時作用于整個集合的任務(wù)。 boolean contains A ll(Collection collection) boolean addAl

16、l(Collectioncollection) voidclear() voidremoveAll(Collectioncollection)voidretainAll(CoIlection collection)containsAllO方法允許您查找當(dāng)前集合是否包含了另一個集合的所有元素,即另一個集合是 否是當(dāng)前集合的子集。其余方法是可選的,因為特定的交合可能不支持集合更改。addAIK) 方法確保另一個集合中的所有元素都被添加到當(dāng)前的集合中,通常稱為并。clear()方法從 當(dāng)前集合中除去所有元素。removeAHO方法類似于clear。,但只除去了元素的一個子集。 retainAlK)方

17、法類似于removeAHO方法,不過可能感到它所做的與前面正好相反:它從當(dāng) 前集合中除去不屬于另一個集合的元素,即交。我們看一個簡單的例子,來了解一下集合類的基本方法的使用:import java.util.*;public class CollectionToArray public static void main(Stringf args) Collection collection l=new Array List。;/創(chuàng)建一個集合對象collection 1.(1(“000”);添力口對象至1 Collection 集合中collectionl.add(,lir,);collecti

18、on l.add(H222N);System.out.printin(集合 collection 1 的大?。?collectionLsize。);System.out.printin(集合 collection 1 的內(nèi)容:+coHectionl);collection Lremove(”00(T);從集合 collection 1 中移除掉 “000”這個對象System.out.println(集合 collection1移除 000 后的內(nèi)容:+collectionl);System.out.printing集合 collection中是否包含 000 : Collection 1 .

19、contains(M000H);System.out.printing集合 collection 1 中是否包含 111 : M+collection 1 .contains(H 111M); Collection collection2=new ArrayListO;collection2.addAll(collection 1)y/ collection1集合中的元素全部都加到 collection2中System.out.printin(集合 collection!的內(nèi)容:+coHection2);collection2.clear();/清空集合 collection 1 中的元素Sy

20、stem.out.println(集合 collection2 是否為空:,r+collection2.isEmpty();將集合collection 1轉(zhuǎn)化為數(shù)組Object s= collection 1 .toArrayO;for(int i=O;is.length;i+)System.out.println(si);)運行結(jié)果為:集合collection 1的大小:3集合 collectionl 的內(nèi)容:000, 111,222集合collectionl移除000后的內(nèi)容:口 11,222集合collection1中是否包含000 : false集合collectionl中是否包含11

21、1 : true集合 collection2的內(nèi)容:111,222集合collection2是否為空:true111222這里需要注意的是,Collection它僅僅只是一個接口,而我們真正 使用的時候,確是創(chuàng)建該接口的一個實現(xiàn)類。做為集合的接口,它定義 了所有屬于集合的類所都應(yīng)該具有的一些方法。而ArrayList (列表)類是集合類的一種實現(xiàn)方式。這里需要一提的是,因為Collection的實現(xiàn)基礎(chǔ)是數(shù)組,所以有轉(zhuǎn) 換為Object數(shù)組的方法: Object toArray() Object toArray(Object a)其中第二個方法Object口 toArray(Object a)

22、的參數(shù)a應(yīng)該是集 合中所有存放的對象的類的父類。1.2.2 迭代器任何容器類,都必須有某種方式可以將東西放進去,然后由某種方 式將東西取出來。畢竟,存放事物是容器最基本的工作。對于ArrayLis t, add ()是插入對象的方法,而get()是取出元素的方式之一。ArrayL ist很靈活,可以隨時選取任意的元素,或使用不同的下標(biāo)一次選取多個 元素。如果從更高層的角度思考,會發(fā)現(xiàn)這里有一個缺點:要使用容器, 必須知道其中元素的確切類型。初看起來這沒有什么不好的,但是考慮 如下情況:如果原本是ArrayList ,但是后來考慮到容器的特點,你想 換用Set ,應(yīng)該怎么做?或者你打算寫通用的代

23、碼,它們只是使用容器, 不知道或者說不關(guān)心容器的類型,那么如何才能不重寫代碼就可以應(yīng)用 于不同類型的容器?所以迭代器(Iterator)的概念,也是出于一種設(shè)計模式就是為達成 此目的而形成的。所以Collection不提供get。方法。如果要遍歷Collec tin中的元素,就必須用Iteratoro迭代器(Iterator)本身就是一個對象,它的工作就是遍歷并選擇 集合序列中的對象,而客戶端的程序員不必知道或關(guān)心該序列底層的結(jié) 構(gòu)。此外,迭代器通常被稱為“輕量級”對象,創(chuàng)建它的代價小。但是, 它也有一些限制,例如,某些迭代器只能單向移動。Collection 接口的 iterator ()

24、方*去返回個 Iteratoro I terat or和您可能已經(jīng)熟悉的Enumeration接口類似。使用Iterator接 口方法,您可以從頭至尾遍歷集合,并安全的從底層Collection中 除去元素。下面,我們看一個對于迭代器的簡單使用:import j ava.util.ArrayLi st;import j ava.util.Collection;import j ava.util.Iterator;public class IteratorDemo public static void main(String args) Collection collection = new A

25、rrayList(); collection.add (Hsln);collection.add (Hs2H);collection . add (Hs3,r);Iterator iterator = collection, iterator () ; . /j1 ,個迭代器while (iterator.hasNext () ) /遍歷Obj ect element = iterator.next ();System.out.printiniterator = + element);if(collection.i sEmpty()System.out.println(Hcollection

26、i s Empty!); elseSystem.out.println(ncollection is not Empty! size = , + collection . size ();Iterator iterator2 = collection.iterator ();while ( iterator2.hasNext() ) / 移除元 素Obj ect element = iterator2.next();System.out.printin(remove: +element);iterator2 remove ();)Iterator iterators = collection.

27、iterator ();if ( ! iterators .hasNext () ) / /察彳 i 是否還仃元索 System.out.println (還有兀素”);)if(collection.isEmpty()System.out.println(Hcollection i s Empty!H);/使用 collection . isEmpty ()方法來判斷 程序的運行結(jié)果為:iterator = s1iterator = s2iterator = s 3collection i s not Empty! s i z e = 3remove: s1remove: s 2remove:

28、 s 3還有元素collection is Empty!可以看到,Java的Collection的Iterator能夠用來,:1) 使用方法iterator。要求容器返回一個Iterator .第一次調(diào) 用Iterator的next。方法時,它返回集合序列的第一個元素。2)使用next。獲得集合序列的中的下一個元素。3)使用hasNext。檢查序列中是否元素。4) 使用remove。將迭代器新返回的元素刪除。需要注意的是:方法刪除由next方法返回的最后一個元素,在每次 調(diào)用next時、remove方法只能被調(diào)用一次。大家看,Java實現(xiàn)的這個迭代器的使用就是如此的簡單。Iterator (跌

29、代器)雖然功能簡單,但仍然可以幫助我們解決許多問題,同時針 對List還有一個更復(fù)雜更高級的Listiterator。您可以在下面的List講 解中得到進一步的介紹。L3 List1.3.1 概述牛述的Collection:接的 類 而List Q容器的一種,表示列表的意思。當(dāng)我們不知道存儲的數(shù)據(jù)有多少的情況,我們就可以使用List來完成存儲數(shù)據(jù)的工作。例如前而提到的一種場景。我們想要在保存一個應(yīng)用系統(tǒng)當(dāng)前的在線用戶的信息。我們就可以使用一個Li st來存儲。因為List的最大的特點就是能夠自動的根據(jù)插入的數(shù)據(jù)量來動態(tài) 改變?nèi)萜鞯拇笮 O露覀兿瓤纯碙ist接口的一些常用方法。1.3.2 常用

30、方法List就是列表的意思,它是Collection的一種,即繼承了 Collection接口,以定義一個允許重復(fù)項的有序集合。該接口不但能夠?qū)α斜淼囊徊糠诌M行 處理,還添加了面向位置的操作。List是按對象的進入順序進行保存對象,而工有的方法外還擁有一不做排序或編輯操作。Collection他的方法1而向位置的操作包括插入某個元素或Collection的功能,還包括獲取、 除去或更改元素的功能。在List中搜索元素可以從列表的頭部或尾部開始, 如果找到元素,還將報告元素所在的位置。 void add(int index, Object element):添加對象 element 到位置 in

31、de X上 boolean addAll(int index, Collection collection):在 index 位置后添 加容器collection中所有的元素 Object get(int index):取出下標(biāo)為index的位置的元素 int indexOf(Object element):查找對象 element 在 List 中第一次出 現(xiàn)的位置 int lastIndexOf(Object element):查找對象 element 在 List 中最后出 現(xiàn)的位置 Object remove(int index):刪除 index 位置上的元素 Object set(

32、int index. Object element):將 index 位置上的對象替換為 element并返回老的元素。先看一下下面表格:簡述實現(xiàn)操作特性成員要求List提供基于索引 的對成員的隨 機訪問ArrayList提供快速的基于索引的成員訪 問,對尾部成員的增加和刪除 支持較好成員可為任意 Object子類的對象LinkedList對列表中任何位置的成員的增 加和刪除支持較好,但對基于 索引的成員訪問支持性能較差成員可為任意 Object子類的對象在集合框架”中有兩種常規(guī)的List實現(xiàn):ArrayList和Linked Listo使用兩種List實現(xiàn)的哪一種取決于您特定的需要。如果要支

33、 持隨機訪問,而不必在除尾部的任何位置插入或除去元素,那么,Arr ayList提供了可選的集合。但如果,您要頻繁的從列表的中間位置添 加和除去元素,而只要順序的訪問列表元素,那么,LinkedList實現(xiàn) 更好。我們以ArrayList為例,先看一個簡單的例子:例子中,我們把12個月份存放到ArrayList中,然后用一個循環(huán), 并使用get ()方法將列表中的對象都取出來。而LinkedList添加了一些處理列表兩端元素的方法(下圖只顯示了新方 法):使用這些新方法,您就可以輕松的把LinkedList當(dāng)作一個堆棧、隊列或 其它而向端點的數(shù)據(jù)結(jié)構(gòu)。import j ava.util.*;p

34、ublic class Li stExample public static void main (String args ) LinkedList queue = new LinkedList();queue.addFirst(Bernadine);queue.addFirst (HElizabeth);queue.addFirst (Gene);queue.addFirst ( Elizabeth);queue.addFirst ( HC1aran);System.out.pr intIn(queue);queue.removeLas t();queue.removeLas t();Sys

35、tem.out.pr intIn(queue);)運行程序產(chǎn)生了以下輸出。請注意,Set1的是List允Clara, Elizabeth, Gene, Elizabeth, BernadineClaraA Elizabeth, Gene該的程序演示了具體List類的使用。第一部分,創(chuàng)建一個由ArrayLis t支持的List。填充完列表以后,特定條目就得到了。示例的LinkedList 部分把LinkedList當(dāng)作一個隊列,從隊列頭部添加?xùn)|西,從尾部除去。List接口不但以位置友好的方式遍歷整個列表,還能處理集合的子集: Listiterator listlterator():返回一個 Li

36、stiterator 跌代器,默認(rèn)開始位置為0 Listiterator listlterator(int startindex): 返回 一Listlterat or跌代器,開始位置為startindex List subList(int fromlndex, int tolndex):返回一個子列表 List ,元素存放為從fromlndex到tolndex之前的一個元素。處理subList ()時,位于fromlndex的元素在子列表中,而位于to Index的元素則不是,提醒這一點很重要。以下for-loop測試案例大致反 映了這一點:for (int i=fromlndex; ito

37、lndex; i+) / process element at position i此外,我們還應(yīng)該提醒的是:對子列表的更改(如add。、remove ()和 set ()調(diào)用)對底層List也有影響。Listiterator 接口Listiterator接口繼承Iterator接口以支持添加或更改底層集合中 的元素,還支持雙向訪問。以下源代碼演示了列表中的反向循環(huán)。請注意Listiterator最初位于 列表尾之后(list.size(),因為第一個元素的下標(biāo)是0。List list = .;ListIterator iterator = list.listiterator(list.siz

38、e();while (iterator.hasPrevious() Object element = iterator.previous ();/ Process element)正常情況下,不用Listiterator改變某次遍歷集合元素的方向一向 前或者向后。雖然在技術(shù)上可能實現(xiàn)時,但在previous ()后立刻調(diào)用nex to ,返回的是同一個元素。把調(diào)用next()和previous()的順序顛倒一下, 結(jié)果相同。我們看一個List的例子:import j ava.util.*;public class ListlteratorTest public static void main

39、(String args) List list = new ArrayList();list . add (aaa11);list.add(nbbb);list.add(H ccc);list . add(nddd);System.out.printin (,r0 +listiterator (0).next ( ) ) ;/next ()System.out.printin (n 卜標(biāo) 1:n + list.listiterator (1).next ();System.out.printin ( M p List 1-3:H +subLi s t(1,3);/子列表List Iterato

40、r it = list.listiterator ();.默 認(rèn)從 卜林 0 JI, 始/隱式光標(biāo)屬性add操作,插入到當(dāng)前的下標(biāo)的前面 it.add(HsssH);while ( it.hasNext() ) System, out .printin ( H n e : t I ndex= n + i t . next Index () + ”, Obj ect = n + it.next ();)/set屬性ListIterator it1 = list.listiterator ();itl.next ();itl . set; ( H ooo n );ListIterator it2

41、= list.listiterator (list.size ();下標(biāo)while (it2.hasPrevious () ) System.out.println(Hprevious Index= n + i 12.previous Index(),Ob j ect = H + it2.previous ();)程序的執(zhí)行結(jié)果為:下標(biāo)。開始:aaa下標(biāo)1開始:bbb子 Lis t 1-3: bbb r ccc next Inde:-: = l, Ob j ect = aaa next Inde:-: = 2 , Ob j ect=bbb next Inde: = 3 , Ob j ect =

42、 ccc next Index = 4,Obj ect = ddd previous Index = 4 rObj ect = ddd previous Index = 3,Obj ect = ccc previous Index = 2,Obj ect=bbb previous Index = l,Obj ect = aaa previous Index=0,Object=ooo我們還需要稍微再解釋一下add()操作。添加一個元素會導(dǎo)致新 元素立刻被添加到隱式光標(biāo)的前面。因此,添加元素后調(diào)用previous ()會返回新元素,而調(diào)用next()則不起作用,返回添加操作之前的 下一個元素。下標(biāo)

43、的顯示方式,如下圖所示:對于List的基本用法我們學(xué)會了,下面我們來進一步了解一下List的實現(xiàn) 原理,以便價升我們對于集合的理解。1.3.3 實現(xiàn)原理前面已經(jīng)提了一下Collection的實現(xiàn)基礎(chǔ)都是基于數(shù)組的。下面我 們就已ArrayList為例,簡單分析一下ArrayList列表的實現(xiàn)方式。首 先,先看下它的構(gòu)造函數(shù)。下列表格是在SUN提供的API中的描述:ArrayList () Constructs an empty list with an initial capacity of ten.ArrayList (Collection c) Constructs a list cont

44、aining the elements of thespecified collection, in the order they are returned by the collections iterator.ArrayList (int initialcapacity) Constructs an empty list with thespecified initial capacity.其中第個構(gòu)造函數(shù)ArrayList ()和第二構(gòu)造函數(shù)ArrayList (Collectio n c)是按照Collection接口文檔所述,所應(yīng)該提供兩個構(gòu)造函數(shù), 一個無參數(shù),一個接受另一個Col

45、lectiono第3個構(gòu)造函數(shù):ArrayList (int initialcapacity) 是 ArrayList 實現(xiàn)的比較重要的 構(gòu)造函數(shù),雖然,我們不常用它,但是某認(rèn)的構(gòu)造函數(shù)正是調(diào)用的該帶參數(shù):i nitialCapacity的構(gòu)造函數(shù)來實現(xiàn)的。其中參數(shù):initialcapacity表 示我們構(gòu)造的這個ArrayList列表的初始化容量是多大。如果調(diào)用默認(rèn)的構(gòu)造 函數(shù),則表示默認(rèn)調(diào)用該參數(shù)為initialcapacity =10的方式,來進行構(gòu)建 一個ArrayList列表對象。為了更好的理解這個initialcapacity參數(shù)的概念,我們先看看Array List在Sun提供

46、的源碼中的實現(xiàn)方式。先看一下它的屬性有哪些:ArrayList繼承了 Abstract Li st我們主要看看Ar r ayLi s t中的屬性 就可以了。ArrayList中主要包含2個屬性: private transient Obj ect elementData; private int size;其中數(shù)組:elementData 是列表的實現(xiàn)核心屬性:數(shù)組。我們使用 該數(shù)組來進行存放集合中的數(shù)據(jù)。而我們的初始化參數(shù)就是該數(shù)組構(gòu)建時候的長 度,即該數(shù)組的length屬性就是initialCapacity參數(shù)。Keys: transient衣示被修飾的屬性不是對象持久狀態(tài)的一部分,不會自

47、 劭的序列化;第2個屬性:size表示列表中真實數(shù)據(jù)的存放個數(shù)。我們再來看一下ArrayList的構(gòu)造函數(shù),加深一下ArrayList是基于數(shù) 組的理解。從源碼中可以看到默認(rèn)的構(gòu)造函數(shù)調(diào)用的就是帶參數(shù)的構(gòu)造函數(shù):public ArrayList(int initialcapacity)不過參數(shù) initiaJ.Capacity= 10。我們主要看ArrayList (int initialcapacity) 這個構(gòu)造函數(shù)??梢?看到:this.elementData = new ObjectinitialCapacity;我們就是使用的initialcapacity 這個參數(shù)來創(chuàng)建一個Obje

48、ct數(shù)組。而我們所有的往該集合對象中存放的數(shù)據(jù),就是存放到了這個Object數(shù)組中去 了。我們在看看另外一個構(gòu)造函數(shù)的源碼:這里,我們先看size()方法的實現(xiàn)形式。它的作用即是返回size屬性值 的大小。然后我們再看另外一個構(gòu)造函數(shù)public ArrayList (Collection c),該構(gòu)造函數(shù)的作用是把另外一個容器對象中的元素存放到當(dāng)前的List 對象中??梢钥吹剑紫?,我們是通過調(diào)用另外一個容器對象C的方法size()來設(shè) 置當(dāng)前的List對象的size屬性的長度大小。接下來,就是對elementData 數(shù)組進行初始化,初始化的大小為原先容器大小的1.1倍。最后,就是通過使用

49、容器接口中的Object toArray(O bject a)方法來把當(dāng)前容器中的對象都存放到新的數(shù)組elementDat a中。這樣就完成了一個ArrayList的建立??赡艽蠹視嬖谝粋€問題,那就是,我們建立的這個ArrayList 是使用 數(shù)組來實現(xiàn)的,但是數(shù)組的長度一旦被定下來,就不能改變了。而我們在給Ar rayList對象中添加元素的時候,卻沒有長度限制。這個時候,ArrayList 中的elementData屬性就必須存在一個需要動態(tài)的擴充容量的機制。我們看 下而的代碼,它描述了這個擴充機制:這個方法的作用就是用來判斷當(dāng)前的數(shù)組是否需要擴容,應(yīng)該擴容多少。其 中屬性:modCou

50、nt是繼承自父類,它表示當(dāng)前的對象對elementData數(shù)組進 行了多少次擴容,清空,移除等操作。該屬性相當(dāng)于是一個對于當(dāng)前List對 象的一個操作記錄日志號。我們主要看下面的代碼實現(xiàn):1 .首先得至Ij當(dāng)前elementData 屬性的長度oldCapacity。2 .然后通過判斷。dCapacity和minCapacity參數(shù)誰大來決定是否需要擴容 如果minCapacity大于oldCapacity,那么我們就對當(dāng)前 的List對象進行擴容。擴容的的策略為:取(oldCapacity * 3)/2 + 1和minCapacity之間更大的那個。然后使用數(shù)組拷 貝的方法,把以前存放的數(shù)據(jù)

51、轉(zhuǎn)移到新的數(shù)組對象中 如果minCapacity不大于oldCapacity那么就不進行擴容。下面我們看看上的那個ensureCapacity方法的是如何使用的:上的兩個a d d方法都是往List中添加元素。每次在添加元素的時候, 我們就需要判斷一下,是否需要對于當(dāng)前的數(shù)組進行擴容。我們主要看看 public boolean add (Object。)方法,可以發(fā)現(xiàn)在添 加一個元素到容器中的時候,首先我們會判斷是否需要擴容。因為只增加一個元 素,所以擴容的大小判斷也就為當(dāng)前的size + 1來進行判斷。然后,就把新添加 的元素放至IJ數(shù)組elementData中。第二個方法 public b

52、oolean addAll (Collection c)也是同樣的原 理。將新的元素放到elementData數(shù)組之后。同時改變當(dāng)前List對象的si ze屬性。類似的List中的其他的方法也都是基于數(shù)組進行操作的。大家有興趣 可以看看源碼中的更多的實現(xiàn)方式。最后我們再看看如何判斷在集合中是否己經(jīng)存在某一個對象的:由源柞馬中我們可以看至lj, public boolean contains (Object elem)方 法是通過調(diào)用public int indexOf (Object elem)方法來判斷是否在集合 中存在某個對象elemo我們看看indexOf方法的具體實現(xiàn)。 首先我們判斷一

53、下elem 對象是否為null ,如果為null的話,那么遍歷數(shù)組elementData 把第一個出現(xiàn)null的位置返回。 如果elem不為null的話,我們也是遍歷數(shù)組elementData , 并通過調(diào)用elem對象的equal s ()方法來得到第一個相等的元素的 位置。這里我們可以發(fā)現(xiàn),ArrayList中用來判斷是否包含一個對象,調(diào)用的是 各個對象自己實現(xiàn)的equals ()方法。在前面的高級特性里面,我們可以知道: 如果要判斷一個類的一個實例對象是否等于另外一個對象,那么我們就需要自己 覆寫 Ob j ect 類的 publ ic boolean equals (Obj ect o

54、b j ) 方法。如果不 覆寫該方法的話,那么就會調(diào)用Object的equals ()方法來進行判斷。這就相 當(dāng)于比較兩個對象的內(nèi)存應(yīng)用地址是否相等了。在集合框架中,不僅僅是List,所有的集合類,如果需要判斷里面是否 存放了的某個對象,都是調(diào)用該對象的equals。方法來進行處理的。1.4 Map1.4.1 概述數(shù)學(xué)中的映射關(guān)系在Java中就是通過Map來實現(xiàn)的。它表示,里面存儲的 元素是一個對(pair),我們通過一個對象,可以在這個映射關(guān)系中找到另外一 個和這個對象相關(guān)的東西。前而提到的我們對于根據(jù)帳號名得到對應(yīng)的人員的信息,就屬于這種情況的 應(yīng)用。我們講一個人員的帳戶名和這人員的信息作

55、了一個映射關(guān)系,也就是說, 我們把帳戶名和人員信息當(dāng)成了一個“鍵值對,“鍵”就是帳戶名,“值”就是 人員信息。下而我們先看看Map接口的常用方法。1.4.2 常用方法Map 接口不是 Collection 接口L而是從自己的用于維護鍵-值46/49關(guān)聯(lián)的接口層次結(jié)構(gòu)入手。按定義,該接口描述了從不重復(fù)的鍵到值的映射。我們可以把這個接口方法分成三組操作:改變、查詢和提供可選視圖。改變操作允許您從映射中添加和除去鍵-值對。鍵和值都可以為nullo但 是,您不能把Map作為一個鍵或值添加給自身。 Object put (Ob j ect key, Ob j ect value ): 用來存放一個鍵-值

56、對Map中 Object remove (Object key):根據(jù) key(鍵),移除一個鍵-值對,并將值返回 匹id putAll (Map mapping):將 另夕卜一個 Map 中元素存入 ,前的Map中 void clear ():清空當(dāng)前Map中的元素查詢操作允許您檢查映射內(nèi)容: Object get (Ob j ect key):根據(jù) key(鍵)取得對應(yīng)的值 boolean containsKey (Object key): 判斷 Map中是否存在某鍵(key) boolean cont ainsValue (Object value):判斷Map中是否存在某值(value ) int size ():返回Map中 鍵-值對的個數(shù) boolean isEmpty

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論