程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> java api之實現(上)

java api之實現(上)

編輯:關於JAVA

實現

實現是用來存儲對象集 的實際數據對象,它實現了在前面的章節中所描述的 核心 對象集 接口 。以下章節將描述三種實現:

通用實現

通用實現是公共類,它提供核心對象集接口的主要實現。

包裝器實現

包裝器實現與其它實現(通常為通用實現)一起提供附加功能。

便利實現

便利實現是小型實現,通常可通過靜態方法(static factory methods)獲得,它可方便、高效地為特殊 對象集 (象 singleton sets)替代通用實現。

另外,根據JDK的abstract implementations,你也可以建立自己的實現。這在一個單獨的課程中有所描述,因為它屬於高級課程。它不是特別難,但相對來講,需要它的人很少。

通用實現

如下表格對通用實現做了小結。該表突出顯示了它們的正常命名樣式:名稱均屬於 形式, 這裡的 是由類實現的核心對象集接口, 而 表示了在該實現底層的數據結構。

       實現 Hash Table Resizable Array Balanced Tree Linked List 接口 Set HashSet   TreeSet   List   ArrayList   LinkedList Map HashMap   TreeMap  

JDK 1.2 提供了每個接口的兩種實現 (Collection是個例外,它沒有直接的實現,但可當作其它 對象集 接口的最小公分母). 在每一個接口中,其中一種實現明顯的是主實現: 要使用的那個,其它東西是一樣的。主實現是 HashSet, ArrayList 和 HashMap. 注意SortedSet和SortedMap接口在上表中沒有列出。它們各自都有一個實現,這些實現(TreeSet 和 TreeMap) 被列在 Set 和 Map 欄裡。

這些實現不僅具有一致的名稱,而且還有一致的行為。它們都實現所有的包含在它們的接口中的選項操作(optional operations),都允許 null 元素、鍵和值。每一種實現都是不同步的。它們都具有快速失效迭代功能, 這可以在迭代過程中檢測非法並發更改,並快速徹底地失效,而不是冒在今後不可預知的時間裡發生任意不可確定行為的風險。所有的實現都是可序列化的(Serializable), 並都支持公共 clone 方法。

新實現不同步這一事實代表與過去的一個中斷:Vector 和 Hashtable 在 JDK 1.2 以前的版本中是同步的。之所以采用新的做法是因為 對象集 經常以一種同步在其中沒有益處的方式所使用。這樣的使用包括單線程使用、只讀使用以及作為一個較大的數據對象(它有它自己的同步)的一部分而使用。通常,API設計的慣例是不讓用戶為不必要的性能花錢。再者,不必要的同步在某中情況下可能會導致死鎖。

如果你需要一個同步的 對象集, synchronization wrappers(同步包裝器)(將在 下一節介紹)允許任意 對象集 轉換為同步對象集。因此,對新的 對象集 實現來說,當它對舊的 對象集 是強制性的時候,同步是可選的。 作為一個經驗法則,你應該考慮的是接口,而不是實現。這就是為什麼在這一節中沒有編程實例的原因。對大部分情況來講,實現的選擇僅影響性能。首選的風格(就象在 接口課程 中所提到的)是在創建一個 對象集 時選擇一個實現,並立即將一個新的 對象集 賦值給相應接口類型的一個變量(或將該 對象集 傳遞給參數為此接口類型的方法)。這樣,程序將不會依賴於在一個給定的實現中任意增加的方法, 並給程序員和維護人員以迅速改變實現的自由(如果有關性能允許這樣做的話)。

下面將簡要討論通用實現。實現的性能的描述使用詞匯如 constant, log, linear, n log(n) 和 quadratic等。這些詞匯指執行操作的關於時間復雜性(time complexity)的漸進上限(asymptotic upper bound)。 所有這些可夠你消化的了,不過如果你不理解,也沒太大關系。有興趣的話可以閱讀任意一本算法教科書,那上面有關於這類內容的解釋。有一件事是應該牢記的,那就是:這種性能的度量有它的局限性。有時名義上較慢的實現對於你所實際使用大小的對象集來說可能要快。如果有些懷疑,估量一下該性能。

Set

兩個通用Set實現是HashSet 和TreeSet。要決定用哪一個,那是非常簡單明了的。 HashSet 要快得多 (對大多數操作是常數時間之於對數時間(constant time vs. log time)), 但不提供排序保證。如果你需要使用 SortedSet 中的操作,或者按順序迭代對你來說是重要的,那麼請使用 TreeSet。 否則,使用 HashSet。 在大多數時間都不使用 HashSet ,對你來說是個公平的賭博。

關於 HashSet,有一件事應該牢記,即就條目數和容量之和來講,迭代是線性的。因此,如果迭代性能很重要,那就應該慎重選擇一個適當的初始容量。容量選得太大,既浪費空間,也浪費時間。 默認的初試容量是101, 一般來講,它比你所需要的要多。可以使用 int 構造函數來指定初始容量。要分配 HashSet 的初始容量為17:

Set s= new HashSet(17);

HashSets 另有一個稱作 裝載因數(load factor) 的"調整參數(tuning parameter)" 。如果你非常在乎你的 HashSet 的空間的使用,請閱讀 HashSet 文本以獲取詳細信息。否則,就使用默認值吧。如果你接受默認裝載因數,但你確實又想指定初始容量,那麼,選一個大約是你期望你的 Set 將增長到的容量的兩倍的數。如果你的猜測不著邊,它也可以增長,或只是浪費一點空間。但都沒有大問題。如果你知道有關正確尺寸的一個最佳值,用它吧;如果不知道,那就使用一個舊的值,或使用一個偶數值。它真的不是非常重要。這些事情只能使 HashSet 稍稍變好一點點。

TreeSet 沒有調整參數。除 clone 之外,HashSet 和 TreeSet 都僅有那些由它們各自的接口所要求的操作 (Set 和 TreeSet),而沒有任何別的操作。

List

兩個通用List實現是ArrayList和LinkedList。 大部分情況下,你可能使用 ArrayList。 它提供常數時間定位存取,並且非常快。因為它不必為 List 中的每個元素分配一個節點對象,並且當它必須立即移動多個元素時,它可以利用本地方法 System.arraycopy 。 你可將 ArrayList 當作沒有同步系統開銷的 Vector 。

如果你經常添加元素至 List 的開始處,或在 List 上迭代以從其內部刪除元素,你可能會考慮使用 LinkedList。這些操作在 LinkedList 中是常數時間,而在 ArrayList 中是線性時間。 但是你付出了很大的代價! 定位存取在 LinkedList 中是線性時間 ,而在 ArrayList 中是常數時間。 進一步講,LinkedList 的常數因數是非常糟糕的。如果你想要使用一個 LinkedList, 用 LinkedList 和 ArrayList 二者去估量它的性能吧,你可能會有意外的收獲。

ArrayList 有一個調整參數,即初始容量(initial capacity). 它是指 ArrayList 在增長前可容納的元素的數量。關於這一點,沒有許多要講的。List 所不需要的僅有的 ArrayList 操作是 ensureCapacity 和 trimToSize (它改變了過剩的容量), 和 clone。

LinkedList 沒有調整參數, 但有7個選項操作,其中一個就是clone,另外6個是 addFirst, getFirst, removeFirst, addLast, getLast, 和 removeLast。 對於它們,我的感覺是復雜的。它們使得將 LinkedList 作為一個隊列或一個雙端隊列(dequeue)來使用這件工作變得簡單, 但是它們也使你在發現 ArrayList 更快時很難轉換你的表達方法。

如果你需要同步,Vector 將稍微快於用Collections.synchronizedList 同步的 ArrayList 。但是 Vector 有早期操作的負擔。因此需格外小心,並總是用 List 接口來操縱 Vector ,否則,你會被它纏住的。

如果你的 List 的大小是固定的 (也就是說,你不會使用 remove, add 或任何其它出 containsAll 以外的批量操作),那麼你有第三個選擇,那肯定是值得考慮的。請看 便利實現(convenience implementations) 一節中的 Arrays.asList。

Map

兩個通用Map實現是HashMap 和TreeMap . Map 的情況與 Set 完全對等。如果你需要 SortedMap 操作或順序 Collection視圖迭代,去找 TreeMap 吧,或者去找 HashMap。 在 Set 章節 中的其它一切都適用於 Map,所以去重新閱讀它們吧。

完整性要求我們提一下Hashtable。 象 Vector 和 ArrayList 一樣,如果你需要同步,Hashtable 將稍微快於用Collections.synchronizedMap 同步的 HashMap 。再有,Hashtable 也有早期操作的負擔。 因此需格外小心,並總是用 Map 接口來操縱它,否則,你會被它纏住的。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved