java Collection

java_Collection_介紹

 

Collection 

 

1.類集框架 

java.util 包中包含了一些在 Java 2 中新增加的最令人興奮的增強功能:類集。一個類集

(collection)是一組對象。類集的增加使得許多 java.util 中的成員在結構和體系結構上發生 根本的改變。它也擴展了包可以被應用的任務範圍。類集是被所有 Java 程序員緊密關注的 最新型的技術。

除了類集,java.util 還包含了支持範圍廣泛的函數的各種各樣的類和接口。這些類和接 口被核心的 Java 包廣泛使用,同時當然也可以被你編寫的程序所使用。對它們的應用包括 產生僞隨機數,對日期和時間的操作,觀測事件,對位集的操作以及標記字符串。由於 java.util 具有許多特性,因此它是 Java 中最被廣泛使用的一個包。

 

 

2.類集概述

 

Java 的類集(Collection)框架使你的程序處理對象組的方法標準化。在 Java 2 出現之前,

Java 提供了一些專門的類如 Dictionary,Vector,Stack 和 Properties 去存儲和操作對象組。 儘管這些類非常有用,它們卻缺少一個集中,統一的主題。因此例如說使用 Vector 的方法 就會與使用 Properties 的方法不同。以前的專門的方法也沒有被設計成易於擴展和能適應新 的環境的形式。而類集解決了這些(以及其他的一些)問題。

 

 

2.1.設計類集的目的

 

類集框架被設計用於適應幾個目的。首先,這種框架是高性能的。對基本類集(動態數

組,鏈接表,樹和散列表)的實現是高效率的。一般很少需要人工去對這些“數據引擎”編寫 代碼(如果有的話)。第二點,框架必須允許不同類型的類集以相同的方式和高度互操作方 式工作。第三點,類集必須是容易擴展和/或修改的。爲了實現這一目標,類集框架被設計 成包含一組標準的接口。對這些接口,提供了幾個標準的實現工具(例如 LinkedList,HashSet 和 TreeSet),通常就是這樣使用的。如果你願意的話,也可以實現你自己的類集。爲了方 便起見,創建用於各種特殊目的的實現工具。一部分工具可以使你自己的類集實現更加容易。 最後,增加了允許將標準數組融合到類集框架中的機制。

 

2.2.Algorithms

算法(Algorithms)是類集機制的另一個重要部分。算法操作類集,它在 Collections 類 中被定義爲靜態方法。因此它們可以被所有的類集所利用。每一個類集類不必實現它自己的 方案,算法提供了一個處理類集的標準方法。

 

2.3.Iterator

由類集框架創建的另一項是 Iterator 接口。一個迭代程序(iterator)提供了一個多用途 的,標準化的方法,用於每次訪問類集的一個元素。因此迭代程序提供了一種枚舉類集內容

(enumerating the contents of a collection)的方法。因爲每一個類集都實現 Iterator,所以通 過由 Iterator 定義的方法,任一類集類的元素都能被訪問到。



除了類集之外,框架定義了幾個映射接口和類。映射(Maps)存儲鍵/值對。儘管映射 在對項的正確使用上不是“類集”,但它們完全用類集集成。在類集框架的語言中,可以獲得 映射的類集“視圖”(collection-view)。這個“視圖”包含了從存儲在類集中的映射得到的元素。 因此,如果選擇了一個映射,就可以將其當做一個類集來處理。

對於由 java.util 定義的原始類,類集機制被更新以便它們也能夠集成到新的系統裏。所 以理解下面的說法是很重要的:儘管類集的增加改變了許多原始工具類的結構,但它卻不會 導致被拋棄。類集僅僅是提供了處理事情的一個更好的方法。

最後的一點:如果你對 C++比較熟悉的話,那麼你可以發現 Java 的類集技術與在 C++中 定義的標準模板庫(STL)相似。在 C++中叫做容器(container),而在 Java 中叫做類集。

 

3 複合框架中的接口

 

java_Collection_介紹

 

java_Collection_介紹

所謂框架就是一個類庫的集合。集合框架就是一個用來表示和操作集合的統一的架構, 包含了實現集合的接口與類。

除了類集接口之外,類集也使用 Comparator,Iterator 和 ListIterator 接口。簡單地說, Comparator 接口定義了兩個對象如何比較;Iterator 和 ListIterator 接口枚舉類集中的對象。 爲了在它們的使用中提供最大的靈活性,類集接口允許對一些方法進行選擇。可選擇的 方法使得使用者可以更改類集的內容。支持這些方法的類集被稱爲可修改的(modifiable)。 不允許修改其內容的類集被稱爲不可修改的(unmodifiable)。如果對一個不可修改的類集 使用這些方法,將引發一個 UnsupportedOperationException 異常。所有內置的類集都是可修

改的。

Collection 接口是構造類集框架的基礎。它聲明所有類集都將擁有的核心方法。因爲所 有類集實現 Collection,所以熟悉它的方法對於清楚地理解框架是必要的。其中幾種方法可 能會引發一個 UnsupportedOperationException 異常。正如上面解釋的那樣,這些發生在當類 集不能被修改時。當一個對象與另一個對象不兼容,例如當企圖增加一個不兼容的對象到一



個類集中時。將產生一個 ClassCastException 異常。調用 add()方法可以將對象加入類集。注 意 add()帶一個 Object 類型的參數。因爲 Object 是所有類的超類,所以任何類型的對象可以 被存儲在一個類集中。然而原始類型不行。例如,一個類集不能直接存儲類型 int,char, double 等的值。當然如果想存儲這些對象,也可以使用原始類型包裝器。可以通過調用 addAll() 方法將一個類集的全部內容增加到另一個類集中。可以通過調用 remove()方法將一個對象刪 除。爲了刪除一組對象,可以調用 removeAll()方法。調用 retainAll()方法可以將除了一組指 定的元素之外的所有元素刪除。爲了清空類集,可以調用 clear()方法。通過調用 contains() 方法,可以確定一個類集是否包含了一個指定的對象。爲了確定一個類集是否包含了另一個 類集的全部元素,可以調用 containsAll()方法當一個類集是空的時候,可以通過調用 isEmpty() 方法來予以確認。調用 size()方法可以獲得類集中當前元素的個數。toArray()方法返回一個數 組,這個數組包含了存儲在調用類集中的元素。通過在類集和數組之間提供一條路徑,可以 充分利用這兩者的優點。一個更加重要的方法是 iterator(),該方法對類集返回一個迭代程序。 當使用一個類集框架時,迭代程序對於成功的編程來說是至關重要的。

Collection:集合層次中的根接口,JDK 沒有提供這個接口直接的實現類。

Set:不能包含重複的元素。

SortedSet 是一個按照升序排列元素的 Set。

List:是一個有序的集合,可以包含重複的元素。提供了按索引訪問的方式。

Map:包含了 key-value 對。Map 不能包含重複的 key。

SortedMap 是一個按照升序排列 key 的 Map。

 

 

 

 

4.List

 

List 接口擴展了 Collection 並聲明存儲一系列元素的類集的特性。使用一個基於零的下 標,元素可以通過它們在列表中的位置被插入和訪問。一個列表可以包含重複元素。除了由 Collection 定義的方法之外,List 還定義了一些它自己的方法。再次注意當類集不能被修改時,


其中的幾種方法引發 UnsupportedOperationException 異常。當一個對象與另一個不兼容,例 如當企圖將一個不兼容的對象加入一個類集中時,將產生 ClassCastException 異常。對於由 Collection 定義的 add()和 addAll()方法,List 增加了方法 add(int, Object)和 addAll(int, Collection)。 這些方法在指定的下標處插入元素。由 Collection 定義的 add(Object)和 addAll(Collection)的 語義也被 List 改變了,以便它們在列表的尾部增加元素。爲了獲得在指定位置存儲的對象, 可以用對象的下標調用 get()方法。爲了給類表中的一個元素賦值,可以調用 set()方法,指 定被改變的對象的下標。調用 indexOf()或 lastIndexOf()可以得到一個對象的下標。通過調用 subList()方法,可以獲得列表的一個指定了開始下標和結束下標的子列表。subList()方法使得 列表處理十分方便。

 

 

5.Set

 

集合接口定義了一個集合。它擴展了 Collection 並說明了不允許複製元素的類集的特性。 因此,如果試圖將複製元素加到集合中時,add()方法將返回 false。它本身並沒有定義任何 附加的方法。

 

 

6.ShortSet

 

SortedSet 接口擴展了 Set 並說明了按升序排列的集合的特性。當沒有項包含在調用集合 中時,其中的幾種方法引發 NoSuchElementException 異常。當對象與調用集合中的元素不兼 容時,引發 ClassCastException 異常。如果試圖使用 null 對象,而集合不允許 null 時,引發 NullPointerException 異常。

SortedSet 定義了幾種方法,使得對集合的處理更加方便。調用 first()方法,可以獲得集 閤中的第一個對象。調用 last()方法,可以獲得集合中的最後一個元素。調用 subSet()方法,

可以獲得排序集合的一個指定了第一個和最後一個對象的子集合。如果需要得到從集合的第 一個元素開始的一個子集合,可以使用 headSet()方法。如果需要獲得集合尾部的一個子集

合,可以使用 tailSet()方法。

現在,你已經熟悉了類集接口,下面開始討論實現它們的標準類。一些類提供了完整的 可以被使用的工具。另一些類是抽象的,提供主框架工具,作爲創建具體類集的起始點。

 

 

7.ArrayList

 

ArrayList:我們可以將其看作是能夠自動增長容量的數組。利用 ArrayList 的 toArray()返 回一個數組。Arrays.asList()返回一個列表。迭代器(Iterator) 給我們提供了一種通用的方式來 訪問集合中的元素。

ArrayList 類擴展 AbstractList 並實現了 List 接口。ArrayList 支持可隨需要而增長的動態數 組。在 Java 中,標準數組是定長的。在數組創建之後,它們不能被加長或縮短,這也就意

味着你必須事先知道數組可以容納多少元素。但是,你直到運行時才能知道需要多大的數組。

爲了解決這個問題,類集框架定義了 ArrayList。本質上,ArrayList 是對象引用的一個變長數 組。也就是說,ArrayList 能夠動態地增加或減小其大小。數組列表以一個原始大小被創建。 當超過了它的大小,類集自動增大。當對象被刪除後,數組就可以縮小。

•ArrayList 有如下的構造函數

–ArrayList( )

–ArrayList(Collection c)


–ArrayList(int capacity)

–第一個構造函數建立一個空的數組列表。

–第二個構造函數建立一個數組列表,該數組列表由類集 c 中的元素初始化。

–第三個構造函數建立一個數組列表,該數組有指定的初始容量(capacity)。容量是用於存

儲元素的基本數組的大小。當元素被追加到數組列表上時,容量會自動增加。 使用由 toString()方法提供的默認的轉換顯示類集的內容,toString()方法是從

AbstractCollection 繼承下來的。儘管它對簡短的例子程序來說是足夠了,然而很少使用這種 方法去顯示實際中的類集的內容。通常編程者會提供自己的輸出程序。

儘管當對象被存儲在 ArrayList 對象中時,其容量會自動增加。仍可以通過調用

ensureCapacity()方法來人工地增加 ArrayList 的容量。如果事先知道將在當前能夠容納的類集 中存儲許許多多的項時,你可能會想這樣做。在開始時,通過一次性地增加它的容量,就能

避免後面的再分配。因爲再分配是很花時間的,避免不必要的處理可以改善性能。

•ensureCapacity()方法如下所示:

–void ensureCapacity(int cap)

–這裏,cap 是新的容量

相反地,如果想要減小在 ArrayList 對象之下的數組的大小,以便它有正好容納當前項的大 小,可以調用 trimToSize()方法。該方法如下:

–void trimToSize()

當使用 ArrayList 時,有時想要獲得一個實際的數組,這個數組包含了列表的內容。可 以通過調用方法 toArray()來實現它。下面是幾個爲什麼可能想將類集轉換成爲數組的原因, a.對於特定的操作,可以獲得更快的處理時間,b.爲了給方法傳遞數組,而方法不必重載去 接收類集,c.爲了將新的基於類集的程序與不認識類集的老程序集成。

Arrays.asList(),返回一個受指定數組支持的固定大小的列表。(對返回列表的更改會“直 寫”到數組。)此方法同 Collection.toArray 一起,充當了基於數組的 API 與基於 collection 的

API 之間的橋樑。

 

 

8.LinkedList

 

LinkedList 類擴展 AbstractSequentialList 並執行 List 接口。它提供了一個鏈接列表數據結

構。

它具有如下的兩個構造函數,說明如下:

–LinkedList( )

–LinkedList(Collection c)

–第一個構造函數建立一個空的鏈接列表。

–第二個構造函數建立一個鏈接列表,該鏈接列表由類集 c 中的元素初始化 除了它繼承的方法之外,LinkedList 類本身還定義了一些有用的方法,這些方法主要用

於操作和訪問列表。使用 addFirst()方法可以在列表頭增加元素;使用 addLast()方法可以在 列表的尾部增加元素。

它們的形式如下所示:

–void addFirst(Object obj)

–void addLast(Object obj)

–這裏,obj 是被增加的項

調用 getFirst()方法可以獲得第一個元素。調用 getLast()方法可以得到最後一個元素。


它們的形式如下所示:

–Object getFirst( )

–Object getLast( )

爲了刪除第一個元素,可以使用 removeFirst()方法;爲了刪除最後一個元素,可以調用

removeLast()方法。

它們的形式如下所示:

–Object removeFirst( )

–Object removeLast( )

因爲 LinkedList 實現 List 接口,調用 add(Object)將項目追加到列表的尾部,如同 addLast() 方法所做的那樣。使用 add()方法的 add(int, Object)形式,插入項目到指定的位置,如例子程 序中調用 add(1,“A2”)的舉例。注意如何通過調用 get()和 set()方法而使得 LinkedList 中的 第三個元素髮生了改變。爲了獲得一個元素的當前值,通過 get()方法傳遞存儲該元素的下 標值。爲了對這個下標位置賦一個新值,通過 set()方法傳遞下標和對應的新值。

LinkedList 是採用雙向循環鏈表實現的。

利用 LinkedList 實現棧(stack)、隊列(queue)、雙向隊列(double-ended queue )。

 

 

9.Date Structure

 

一般將數據結構分爲兩大類:線性數據結構和非線性數據結構。線性數據結構有線性表、 棧、隊列、串、數組和文件;非線性數據結構有樹和圖。

 

9.1.linear list

線性表的邏輯結構是 n 個數據元素的有限序列:(a1, a2,a3,…an),n 爲線性表的長度(n≥

0),n=0 的表稱爲空表。 數據元素呈線性關係。必存在唯一的稱爲“第一個”的數據元素;必存在唯一的稱爲“最

後一個”的數據元素;除第一個元素外,每個元素都有且只有一個前驅元素;除最後一個元 素外,每個元素都有且只有一個後繼元素。所有數據元素在同一個線性表中必須是相同的數 據類型。

線性表按其存儲結構可分爲順序表和鏈表。用順序存儲結構存儲的線性表稱爲順序表; 用鏈式存儲結構存儲的線性表稱爲鏈表。

將線性表中的數據元素依次存放在某個存儲區域中,所形成的表稱爲順序表。一維數組

就是用順序方式存儲的線性表。

 

9.2.linked list

9.3.Stack

棧(Stack)也是一種特殊的線性表,是一種後進先出(LIFO: last in first out)的結構。棧是限 定僅在表尾進行插入和刪除運算的線性表,表尾稱爲棧頂(top),表頭稱爲棧底(bottom)。棧 的物理存儲可以用順序存儲結構,也可以用鏈式存儲結構。

 

 

 

9.4Queue

隊列(Queue)是限定所有的插入只能在表的一端進行,而所有的刪除都在表的另一端進 行的線性表。表中允許插入的一端稱爲隊尾(Rear),允許刪除的一端稱爲隊頭(Front)。隊列 的操作是按先進先出(FIFO:first in first out)的原則進行的。隊列的物理存儲可以用順序存儲結 構,也可以用鏈式存儲結構。

 

 

 

 

10.ArrayList VS LinkedList

 

ArrayList 底層採用數組完成,而 LinkedList 則是以一般的雙向鏈表(double-linked list)完成,

其內每個對象除了數據本身外,還有兩個引用,分別指向前一個元素和後一個元素。如果我

們經常在 List 的開始處增加元素,或者在 List 中進行插入和刪除操作,我們應該使用 LinkedList , 否則的話,使用 ArrayList 將更加快速。


11.HashSet

 

HashSet 擴展 AbstractSet 並且實現 Set 接口。它創建一個類集,該類集使用散列表進行 存儲。散列表通過使用稱之爲散列法的機制來存儲信息。在散列(hashing)中,一個關鍵 字的信息內容被用來確定唯一的一個值,稱爲散列碼(hash code)。而散列碼被用來當做 與關鍵字相連的數據的存儲下標。關鍵字到其散列碼的轉換是自動執行的——你看不到散列 碼本身。你的程序代碼也不能直接索引散列表。散列法的優點在於即使對於大的集合,它允 許一些基本操作如 add(),contains(),remove()和 size()方法的運行時間保持不變。

NOTE:

•散列表又稱爲哈希表。散列表算法的基本思想是: 以結點的關鍵字爲自變量,通過一定的函數關係(散列函數)計算出對應的函數值,以這個

值作爲該結點存儲在散列表中的地址。

•當散列表中的元素存放太滿,就必須進行再散列,將產生一個新的散列表,所有元素存放 到新的散列表中,原先的散列表將被刪除。在 Java 語言中,通過負載因子(load factor)來決 定何時對散列表進行再散列。例如:如果負載因子是 0.75,當散列表中已經有 75%的位置已 經放滿,那麼將進行再散列。

•負載因子越高(越接近 1.0),內存的使用效率越高,元素的尋找時間越長。負載因子越低(越 接近 0.0),元素的尋找時間越短,內存浪費越多。

•HashSet 類的缺省負載因子是 0.75。

•下面的構造函數定義爲:

–HashSet( )

–HashSet(Collection c)

–HashSet(int capacity)

–HashSet(int capacity, float fillRatio)

•第一種形式構造一個默認的散列集合。

•第二種形式用 c 中的元素初始化散列集合。

•第三種形式用 capacity 初始化散列集合的容量。

•第四種形式用它的參數初始化散列集合的容量和填充比(也稱爲加載容量)。填充比必須 介於 0.0 與 1.0 之間,它決定在散列集合向上調整大小之前,有多少能被充滿。具體的說, 就是當元素的個數大於散列集合容量乘以它的填充比時,散列集合被擴大。對於沒有獲得填

充比的構造函數,默認使用 0.75。

HashSet 沒有定義更多的其他方法。 重要的是,注意散列集合並沒有確保其元素的順序,因爲散列法的處理通常不讓自己參

與創建排序集合。如果需要排序存儲,另一種類集—— TreeSet 將是一個更好的選擇。

 

 

12.TreeSet

 

TreeSet 爲使用樹來進行存儲的 Set 接口提供了一個工具,對象按升序存儲。訪問和檢 索是很快的。在存儲了大量的需要進行快速檢索的排序信息的情況下,TreeSet 是一個很好 的選擇。

•下面的構造函數定義爲:

–TreeSet( )

–TreeSet(Collection c)


–TreeSet(Comparator comp)

–TreeSet(SortedSet ss)

•第一種形式構造一個空的樹集合,該樹集合將根據其元素的自然順序按升序排序。

•第二種形式構造一個包含了 c 的元素的樹集合。

•第三種形式構造一個空的樹集合,它按照由 comp 指定的比較函數進行排序(比較函數將 在後面介紹)。

•第四種形式構造一個包含了 ss 的元素的樹集合。

 

 

 

 

13.Access Collection by Iterator method

 

通常希望循環通過類集中的元素。例如,可能會希望顯示每一個元素。到目前爲止,處 理這個問題的最簡單方法是使用 iterator,iterator 是一個或者實現 Iterator 或者實現 ListIterator 接口的對象。Iterator 可以完成循環通過類集,從而獲得或刪除元素。ListIterator 擴展 Iterator,允許雙向遍歷列表,並可以修改單元

在通過迭代函數訪問類集之前,必須得到一個迭代函數。每一個 Collection 類都提供一 個 iterator()函數,該函數返回一個對類集頭的迭代函數。通過使用這個迭代函數對象,可以

訪問類集中的每一個元素,一次一個元素。通常,使用迭代函數循環通過類集的內容,步驟 如下:

–1. 通過調用類集的 iterator( )方法獲得對類集頭的迭代函數。

–2. 建立一個調用 hasNext( )方法的循環,只要 hasNext( )返回 true,就進行循環迭代。

–3. 在循環內部,通過調用 next( )方法來得到每一個元素。

對於執行 List 的類集,也可以通過調用 ListIterator 來獲得迭代函數。正如上面解釋的那 樣,列表迭代函數提供了前向或後向訪問類集的能力,並可讓你修改元素。否則,ListIterator 如同 Iterator 功能一樣。

Iterator 和 ListIterator。它使用 ArrayList 對象,但是總的原則適用於任何類型的類集。 當然,ListIterator 只適用於那些實現 List 接口的類集。


爲了簡單,前面的例子在類集中存儲內置的對象,如 String 或 Integer。當然,類集並沒 有被限制爲只能存儲內置的對象。完全相反的是,類集的能力是它能存儲任何類型的對象,

包括你所創建的類的對象。

 

 

14.Map

 

除了類集,Java 2 還在 java.util 中增加了映射。映射(map)是一個存儲關鍵字和值的 關聯或者說是關鍵字/值對的對象。給定一個關鍵字,可以得到它的值。關鍵字和值都是對 象。關鍵字必須是唯一的。但值是可以重複的。有些映射可以接收 null 關鍵字和 null 值。而 有的則不行。

Map 接口映射唯一關鍵字到值。關鍵字(key)是以後用於檢索值的對象。給定一個關 鍵字和一個值,可以存儲這個值到一個 Map 對象中。當這個值被存儲以後,就可以使用它 的關鍵字來檢索它。當調用的映射中沒有項存在時,其中的幾種方法會引發一個 NoSuchElementException 異常。而當對象與映射中的元素不兼容時,引發一個 ClassCastException 異常。如果試圖使用映射不允許使用的 null 對象時,則引發一個 NullPointerException 異常。當試圖改變一個不允許修改的映射時,則引發一個 UnsupportedOperationException 異常。

映射循環使用兩個基本操作:get()和 put()。使用 put()方法可以將一個指定了關鍵字和 值的值加入映射。爲了得到值,可以通過將關鍵字作爲參數來調用 get()方法。調用返回該

值。

映射不是類集,但可以獲得映射的類集“視圖”。爲了實現這種功能,可以使用 entrySet() 方法,它返回一個包含了映射中元素的集合(Set)。爲了得到關鍵字的類集“視圖”,可以 使用 keySet()方法。爲了得到值的類集“視圖”,可以使用 values()方法。類集“視圖”是將映射 集成到類集框架內的手段。

 

 

15.ShortMap

 

SortedMap 接口擴展了 Map,它確保了各項按關鍵字升序排序。當調用映射中沒有的項 時,其中的幾種方法引發一個 NoSuchElementException 異常。當對象與映射中的元素不兼容 時,則引發一個 ClassCastException 異常。當試圖使用映射不允許使用的 null 對象時,則引 發一個 NullPointerException 異常。

排序映射允許對子映射(換句話說,就是映射的子集)進行高效的處理。使用 headMap(),

tailMap()或 subMap()方法可以獲得子映射。調用 firstKey()方法可以獲得集合的第一個關鍵字。 而調用 lastKey()方法可以獲得集合的最後一個關鍵字。

 

 

16.Map.Entry

 

Map.Entry 接口使得可以操作映射的輸入。回想由 Map 接口說明的 entrySet()方法,調 用該方法返回一個包含映射輸入的集合(Set)。這些集合元素的每一個都是一個 Map.Entry 對象。


17.HashMap

 

HashMap 類使用散列表實現 Map 接口。這允許一些基本操作如 get()和 put()的運行時間 保持恆定,即便對大型集合,也是這樣的。

•下面的構造函數定義爲:

–HashMap( )

–HashMap(Map m)

–HashMap(int capacity)

–HashMap(int capacity, float fillRatio)

•第一種形式構造一個默認的散列映射。

•第二種形式用 m 的元素初始化散列映射。

•第三種形式將散列映射的容量初始化爲 capacity。

•第四種形式用它的參數同時初始化散列映射的容量和填充比。容量和填充比的含義與前面 介紹的 HashSet 中的容量和填充比相同。

HashMap 實現 Map 並擴展 AbstractMap。它本身並沒有增加任何新的方法。應該注意的 是散列映射並不保證它的元素的順序。因此,元素加入散列映射的順序並不一定是它們被迭 代函數讀出的順序。映射的內容通過使用由調用函數 entrySet()而獲得的集合“視圖”而顯示

出來。關鍵字和值通過調用由 Map.Entry 定義的 getKey()和 getValue()方法而顯示。。put()

方法自動用新值替換與指定關鍵字相關聯的原先的值。

 

 

18.TreeMap

 

TreeMap 類通過使用樹實現 Map 接口。TreeMap 提供了按排序順序存儲關鍵字/值對的 有效手段,同時允許快速檢索。應該注意的是,不像散列映射,樹映射保證它的元素按照關 鍵字升序排序。

•下面的 TreeMap 構造函數定義爲:

–TreeMap( )

–TreeMap(Comparator comp)

–TreeMap(Map m)

–TreeMap(SortedMap sm)

•第一種形式構造一個空樹的映射,該映射使用其關鍵字的自然順序來排序。

•第二種形式構造一個空的基於樹的映射,該映射通過使用 Comparator comp 來排序(比較 函數 Comparators 將在後面進行討論)。

•第三種形式用從 m 的輸入初始化樹映射,該映射使用關鍵字的自然順序來排序。

•第四種形式用從 sm 的輸入來初始化一個樹映射,該映射將按與 sm 相同的順序來排序

TreeMap 實現 SortedMap 並且擴展 AbstractMap。而它本身並沒有另外定義其他方法。

 

19.比較函數

 

TreeSet 和 TreeMap 都按排序順序存儲元素。然而,精確定義採用何種“排序順序”的是 比較函數。通常在默認的情況下,這些類通過使用被 Java 稱之爲“自然順序”的順序存儲它 們的元素,而這種順序通常也是你所需要的(A 在 B 的前面,1 在 2 的前面,等等)。如果


需要用不同的方法對元素進行排序,可以在構造集合或映射時,指定一個 Comparator 對象。 這樣做爲你提供了一種精確控制如何將元素儲存到排序類集和映射中的能力。

Comparator 接口定義了兩個方法:compare( )和 equals( )。這裏給出的 compare( )方法按 順序比較了兩個元素:int compare(Object obj1, Object obj2),obj1 和 obj2 是被比較的兩個對 象。當兩個對象相等時,該方法返回 0;當 obj1 大於 obj2 時,返回一個正值;否則,返回

一個負值。如果用於比較的對象的類型不兼容的話,該方法引發一個 ClassCastException 異 常。通過覆蓋 compare(),可以改變對象排序的方式。例如,通過創建一個顛倒比較輸出的

比較函數,可以實現按逆向排序。這裏給出的 equals( )方法,測試一個對象是否與調用比較

函數相等:boolean equals(Object obj),obj 是被用來進行相等測試的對象。如果 obj 和調用 對象都是 Comparator 的對象並且使用相同的排序。該方法返回 true。否則返回 false。重寫 equals( )方法是沒有必要的,大多數簡單的比較函數都不這樣做。

 

 

20.類集算法

 

類集框架定義了幾種能用於類集和映射的算法。在 Collections 類中,這些算法被定義爲 靜態方法。當試圖比較不兼容的類型時,其中的一些算法引發一個 ClassCastException 異常; 而當試圖改變一個不可改變的類集時,則引發一個 UnsupportedOperationException 異常。注 意其中的幾種方法,如 synchronizedList()和 synchronizedSet()被用來獲得各種類集的同步(安 全線程)拷貝。沒有任何一個標準類集實現是同步的。必須使用同步算法來爲其提供同步。 另一種觀點:同步類集的迭代函數必須在 synchronized 塊內使用。以 unmodifiable 開頭的一 組方法返回不能被改變的各種類集“視圖”。這些方法當將一些進程對類集設爲只讀形式時很 有用的 Collections 定義了三個靜態變量:EMPTY_SET,EMPTY_LIST 和 EMPTY_MAP。它們都 是不可改變的。EMPTY_MAP 是在 Java 2 的 1.3 版中新增加的。注意 min()和 max()方法是在 列表被混淆之後,對其進行操作的。兩者在運行時,都不需要排序的列表。

 

 

21.Arrays

 

Java 2 在 java.util 中新增加了一個叫做 Arrays 的類。這個類提供了各種在進行數組運算 時很有用的方法。儘管這些方法在技術上不屬於類集框架,但它們提供了跨越類集和數組的 橋樑。在這一節中,分析由 Arrays 定義的每一種方法。asList()方法返回一個被指定數組支持 的 List。換句話說,列表和數組訪問的是同一個單元。它具有如下的形式:

–static List asList(Object[ ] array)

–這裏 array 是包含了數據的數組

binarySearch()方法使用二分法搜索尋找指定的值。該方法必須應用於排序數組。它具有 如下的形式:

–static intbinarySearch(byte[ ] array, byte value)

–static intbinarySearch(char[ ] array, char value)

–static intbinarySearch(double[ ] array, double value)

–static intbinarySearch(float[ ] array, float value)

–static intbinarySearch(int[ ] array, intvalue)

–static intbinarySearch(long[ ] array, long value)

–static intbinarySearch(short[ ] array, short value)

–static intbinarySearch(Object[ ] array, Object value)

–static intbinarySearch(Object[ ] array, Object value, Comparator c)


這裏,array 是被搜索的數組,而 value 是被查找的值。當 array 中包含的元素是不可比 較的(例如 Double 和 StringBuffer)或者當 value 與 array 中的類型不兼容時,後兩種形式引 發一個 ClassCastException 異常。在最後一種形式中,比較函數(Comparator)c 用於確定 array 中的元素的順序。在所有的形式中,如果 array 中含有 value,則返回該元素的下標。否則, 返回一個負值。

 

 

22.以前版本遺留下來的類和接口

 

java.util 的最初版本中不包括類集框架。取而代之,它定義了幾個類和接口提供專門的 方法用於存儲對象。隨着在 Java 2 中引入類集,有幾種最初的類被重新設計成支持類集接口。 因此它們與框架完全兼容。儘管實際上沒有類被擯棄,但其中某些仍被認爲是過時的。當然, 在那些重複從以前版本遺留下來的類的功能性的地方,通常都願意用類集編寫新的代碼程序。 一般地,對從以前版本遺留下來的類的支持是因爲仍然存在大量使用它們的基本代碼。包括 現在仍在被 Java 2 的應用編程接口(API)使用的程序。另一點,沒有一個類集類是同步的。 但是所有的從以前版本遺留下來的類都是同步的。這一區別在有些情況下是很重要的。當然, 通過使用由 Collections 提供的算法也很容易實現類集同步。

 

22.1.Enumeration

Enumeration 接口定義了可以對一個對象的類集中的元素進行枚舉(一次獲得一個)的 方法。這個接口儘管沒有被擯棄,但已經被 Iterator 所替代。Enumeration 對新程序來說是 過時的。然而它仍被幾種從以前版本遺留下來的類(例如 Vector 和 Properties)所定義的方 法使用,被幾種其他的 API 類所使用以及被目前廣泛使用的應用程序所使用。

•Enumeration 指定下面的兩個方法:

–boolean hasMoreElements( )

–Object nextElement( )

–執行後,當仍有更多的元素可提取時,hasMoreElements()方法一定返回 true。當所有元素 都被枚舉了,則返回 false。nextElement()方法將枚舉中的下一個對象做爲一個類屬 Object

的引用而返回。也就是每次調用 nextElement()方法獲得枚舉中的下一個對象。調用例程必須

將那個對象轉換爲包含在枚舉內的對象類型

 

22.2.Vector

Vector 實現動態數組。這與 ArrayList 相似,但兩者不同的是:Vector 是同步的,並且它 包含了許多不屬於類集框架的從以前版本遺留下來的方法。隨着 Java 2 的公佈,Vector 被重 新設計來擴展 AbstractList 和實現 List 接口,因此現在它與類集是完全兼容的

•這裏是 Vector 的構造函數:

–Vector( )

–Vector(int size)

–Vector(int size, int incr)

–Vector(Collection c)

•第一種形式創建一個原始大小爲 10 的默認矢量。

•第二種形式創建一個其原始容量由 size 指定的矢量。

•第三種形式創建一個其原始容量由 size 指定,並且它的增量由 incr 指定的矢量。增量指定 了矢量每次允許向上改變大小的元素的個數。

•第四種形式創建一個包含了類集 c 中元素的矢量。這個構造函數是在 Java 2 中新增加的。


所有的矢量開始都有一個原始的容量。在這個原始容量達到以後,下一次再試圖向矢量 中存儲對象時,矢量自動爲那個對象分配空間同時爲別的對象增加額外的空間。通過分配超

過需要的內存,矢量減小了可能產生的分配的次數。這種次數的減少是很重要的,因爲分配 內存是很花時間的。在每次再分配中,分配的額外空間的總數由在創建矢量時指定的增量來 確定。如果沒有指定增量,在每個分配週期,矢量的大小增一倍。

•Vector 定義了下面的保護數據成員:

–int capacityIncrement;

–int elementCount;

–Object elementData[ ];

–增量值被存儲在 capacityIncrement 中。矢量中的當前元素的個數被存儲在 elementCount

中。保存矢量的數組被存儲在 elementData 中。

因爲 Vector 實現 List,所以可以像使用 ArrayList 的一個實例那樣使用矢量。也可以使用 它的從以前版本遺留下來的方法來操作它。例如,在後面實例化 Vector,可以通過調用 addElement()方法而爲其增加一個元素。調用 elementAt()方法可以獲得指定位置處的元素。 調用 firstElement()方法可以得到矢量的第一個元素。調用 lastElement()方法可以檢索到矢量 的最後一個元素。使用 indexOf()和 lastIndexOf()方法可以獲得元素的下標。調用 removeElement()或 removeElementAt()方法可以刪除元素。

隨着 Java 2 的公佈,Vector 增加了對迭代函數的支持。現在可以使用迭代函數來替代枚 舉去遍歷對象。例如,下面的基於迭代函數的程序代碼:

// use an iterator to display contentsIterator vItr = v.iterator();System.out.println(” \nElements in vector:”);while(vItr.hasNext()) System.out.print(vItr.next() + ” “);System.out.println();

因爲建議不要使編寫枚舉新的程序代碼,所以通常可以使用迭代函數來對矢量的內容進

行枚舉。當然,業已存在的大量的老程序採用了枚舉。不過幸運的是,枚舉和迭代函數的工 作方式幾乎相同。

 

 

22.3.Stack

Stack 是 Vector 的一個子類,它實現標準的後進先出堆棧。Stack 僅僅定義了創建空堆棧 的默認構造函數。Stack 包括了由 Vector 定義的所有方法,同時增加了幾種它自己定義的方 法。

 

22.4.Dictionary

字典(Dictionary)是一個表示關鍵字/值存儲庫的抽象類,同時它的操作也很像映射

(Map)。給定一個關鍵字和值,可以將值存儲到字典(Dictionary)對象中。一旦這個值被 存儲了,就能夠用它的關鍵字來檢索它。因此,與映射一樣,字典可以被當做關鍵字/值對

列表來考慮。儘管在 Java 2 中並沒有擯棄字典(Dictionary),由於它被映射(Map)所取代, 從而被認爲是過時的。然而由於目前 Dictionary 被廣泛地使用,因此這裏仍對它進行詳細的

討論。

 

22.5.HashTable

散列表(Hashtable)是原始 java.util 中的一部分同時也是 Dictionary 的一個具體實現。 然而,Java2 重新設計了散列表(Hashtable)以便它也能實現映射(Map)接口。因此現在 Hashtable 也被集成到類集框架中。它與 HashMap 相似,但它是同步的。和 HashMap 一樣, Hashtable 將關鍵字/值對存儲到散列表中。使用 Hashtable 時,指定一個對象作爲關鍵字,


同時指定與該關鍵字相關聯的值。接着該關鍵字被散列,而把得到的散列值作爲存儲在表中 的值的下標。

散列表僅僅可以存儲重載由 Object 定義的 hashCode()和 equals()方法的對象。hashCode() 方法計算和返回對象的散列碼。當然,equals()方法比較兩個對象。幸運的是,許多 Java 內 置的類已經實現了 hashCode()方法。例如,大多數常見的 Hashtable 類型使用字符串(String)

對象作爲關鍵字。String 實現 hashCode()和 equals()方法。

•Hashtable 的構造函數如下所示:

–Hashtable( )

–Hashtable(int size)

–Hashtable(int size, float fillRatio)

–Hashtable(Map m)

•第一種形式是默認的構造函數。

•第二種形式創建一個散列表,該散列表具有由 size 指定的原始大小。

•第三種形式創建一個散列表,該散列表具有由 size 指定的原始大小和由 fillRatio 指定的填 充比。填充比必須介於 0.0 和 1.0 之間,它決定了在散列表向上調整大小之前散列表的充滿 度。具體地說,當元素的個數大於散列表的容量乘以它的填充比時,散列表被擴展。如果沒

有指定填充比,默認使用 0.75。最後,

•第四種形式創建一個散列表,該散列表用 m 中的元素初始化。散列表的容量被設爲 m 中 元素的個數的兩倍。默認的填充因子設爲 0.75。第四種構造函數是在 Java 2 中新增加的。

重要的一點是:和映射類一樣,Hashtable 不直接支持迭代函數。因此,上面的程序使 用枚舉來顯示 balance 的內容。然而,我們可以獲得允許使用迭代函數的散列表的集合視圖。 爲了實現它,可以簡單地使用由 Map 定義的一個類集“視圖”方法,如 entrySet()或 keySet() 方法。例如,可以獲得關鍵字的一個集合“視圖”,並遍歷這些關鍵字。

 

22.6.Properties

屬性(Properties)是 Hashtable 的一個子類。它用來保持值的列表,在其中關鍵字和值 都是字符串(String)。Properties 類被許多其他的 Java 類所使用。例如,當獲得系統環境 值時,System.getProperties()返回對象的類型。

Properties 類的一個有用的功能是可以指定一個默認屬性,如果沒有值與特定的關鍵字 相關聯,則返回這個默認屬性。例如,默認值可以與關鍵字一起在 getProperty()方法中被指

定——如 getProperty(“name”,“default value”)。如果“name”值沒有找到,則返回“default value”。

當構造一個 Properties 對象時,可以傳遞 Properties 的另一個實例做爲新實例的默認值。在

這種情況下,如果對一個給定的 Properties 對象調用 getProperty(“foo”),而“foo”並不存在時, Java 在默認 Properties 對象中尋找“foo”。它允許默認屬性的任意層嵌套。Properties 的一個 最有用的方面是可以利用 store()和 load()方法方便地對包含在屬性(Properties)對象中的信 息進行存儲或從盤中裝入信息。在任何時候,都可以將一個屬性(Properties)對象寫入流 或從中將其讀出。這使得屬性列表特別方便實現簡單的數據庫。

 

 

類集總結

 

類集框架爲程序員提供了一個功能強大的設計方案以解決編程過程中面臨的大多數任 務。下一次當你需要存儲和檢索信息時,可考慮使用類集。

集合框架在我們今後的程序中將會被大量使用。

    </div>
                    <!-- 正文結束 -->
    <div id="share" class="shareUp">
        <div class="share SG_txtb">
        分享: 
        <div class="bshare-custom" style="display:inline;margin-left:5px;"><div class="bsPromo bsPromo2"></div><a title="分享到新浪微博" class="bshare-sinaminiblog" href="javascript:void(0);"></a><a title="分享到微信" class="bshare-weixin" href="javascript:void(0);"></a><a title="分享到QQ空間" class="bshare-qzone" href="javascript:void(0);"></a><a title="分享到豆瓣" class="bshare-douban" href="javascript:void(0);"></a><a title="更多平臺" class="bshare-more bshare-more-icon more-style-addthis"></a>
        </div>
        </div>
        <div class="up">
            <div title="喜歡後讓更多人看到" id="dbox_3fb3625f0101aref" class="upBox upBox_dis" style="cursor: default;">
                <p ti_title="java_Collection_介紹" id="dbox2_3fb3625f0101aref" class="count" mnum="41">42</p>
                <p class="link">已喜歡</p>
            </div>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章