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

java api之實現(下)

編輯:關於JAVA

包裝器實現

包裝器實現是一種將它們的實際工作委托給一個特定對象集的實現,它在該 對象集 所提供的功能之上又增加了額外的功能。對design patterns(設計樣式)愛好者來說,這是一個 decorator(油漆工)樣式。雖然有點異國情調,但確實簡單明了。

這些實現是匿名的:不是提供一個公共類,JDK 提供一個 static factory method(靜態方法)。所有這些都可以在僅包含靜態方法的Collections API 中找到。

同步包裝器(Synchronization Wrappers)

同步包裝器將自動同步(線程安全的)添加到一個任意的 對象集。6個 核心 對象集 接口中的每一個都對應一個靜態方法:

public static Collection synchronizedCollection(Collection c);
public static Set synchronizedSet(Set s);
public static List synchronizedList(List list);
public static Map synchronizedMap(Map m);
public static SortedSet synchronizedSortedSet(SortedSet s);
public static SortedMap synchronizedSortedMap(SortedMap m);

每一個這樣的方法都返回一個由特定 對象集 作為後備的同步(線程安全的)Collection。為保證串行存取,所有對後備 對象集 的存取都必須通過返回的 對象集 來完成,這一點是至關重要的。保證這一點的一個簡便辦法是不要保持對後備 對象集 的引用, 創建這樣的同步 對象集 是一個小技巧:

List list = Collections.synchronizedList(new ArrayList());

一個用這種方式創建的對象集,每一比特都是線程安全的,就象VectorM那樣的"正常"同步 對象集 一樣。在需要並發存取情況下,在返回的 對象集 上迭代時,用戶對返回的 對象集 做手工同步是十分必要的。這是因為迭代是通過對對象集 的多重調用完成的,它必須被編寫為一個單獨的最小單元操作(atomic operation)。在一個包裝器同步的 對象集 上的迭代慣用程序如下所示:

Collection c = Collections.synchronizedCollection(myCollection);
synchronized(c) {
Iterator i = c.iterator(); // Must be in the synchronized block!
while (i.hasNext())
foo(i.next());
}

在一個同步 Map 的 Collection視圖上的迭代慣用程序與上述程序相似,但有一個訣竅,那就是,當在同步 Map 的Collection視圖上迭代時, 用戶必須對同步 Map 做手工同步,而不是對 Collection視圖本身做同步:

Map m = Collections.synchronizedMap(new HashMap());
...
Set s = m.keySet(); // Needn"t be in synchronized block
...
synchronized(m) { // Synchronizing on m, not s!
Iterator i = s.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}

包裝器實現的一個小的缺陷是你不能執行一個包裝器實現的非接口操作。因此,比如在上面的 List 的例子中,你就不能調用包裝的ArrayList上的ensureCapacity 操作。

不可變包裝器(Unmodifiable Wrappers)

從概念上講,不可變包裝器與同步包裝器是相似的,但它要更簡單。它不是在包裝的 對象集 上增加功能,而是減少功能。特別是,它取消了更改 對象集 的功能;辦法是截取所有那些要更改 對象集 的操作,並扔出一個UnsupportedOperationException。不可變包裝器有兩個主要用途:

使一個對象集在一旦建立後就不可在改變。針對這種情況,不保持對後備 對象集 的引用是一個好的做法。它可以絕對保證不可變性。

允許"二等公民(second-class citizens)" 對你的數據結構的只讀訪問。你可以保持對後備 對象集 的引用,但施捨一個對包裝器的引用。用這樣的辦法,二等公民可以看,但不能觸動,而你可以保持全面的存取。

就象同步包裝器一樣,6個核心對象集接口中的每一個接口都對應一個靜態方法:

public static Collection unmodifiableCollection(Collection c);
public static Set unmodifiableSet(Set s);
public static List unmodifiableList(List list);
public static Map unmodifiableMap(Map m);
public static SortedSet unmodifiableSortedSet(SortedSet s);
public static SortedMap unmodifiableSortedMap(SortedMap m);

便利實現(Convenience Implementations)

這一節將描述幾個小型實現。當你不需要一個通用實現的全部功能時,使用小型實現更方便,效率更高。這一節描述的所有實現都可通過靜態方法獲得,或者通過輸出常數(不是公共類)來獲得。

數組的List視圖

Arrays.asList方法返回它的數組參數的一個 List視圖。List 變化會寫在數組上,反之亦然。對象集 的大小就是數組的大小,且不能被改變。如果在該 List 上調用了 add 或 remove 方法,則回導致一個UnsupportedOperationException 。

正常地使用這個實現就象在基於數組的API和基於 對象集 的API之間架起了一座橋梁。它允許你將一個數組傳遞給期望一個 Collection 或一個 List 的方法。然而,這個實現還有另一個用途。如果你需要一個定尺寸 List, 它將比任何通用 List 實現的效率都高。以下是一個慣用程序:

List l = Arrays.asList(new Object[size]);

注意對一個後備數組的引用是不保留的。

不可變多重-拷貝List(Immutable Multiple-Copy List) 偶爾你需要一個不可變的由相同元素的多個拷貝所組成的 List 。Collections.nCopies方法可返回這樣的一個 List。這個實現有兩個用途。一個是初始化一個新創建的 List。例如,假設你要初始化一個 ArrayList,使之包含 1000 個空元素。請看如下咒語:

List l = new ArrayList(Collections.nCopies(1000, null));

當然,每個元素的初始值不必是空。第二個主要用途是增長一個現存 List。例如,假設你要將串 fruit bat 的69個拷貝添加到一個 List 的末尾。不知道你為什麼要這樣做,我們只假設你是要這樣做。下面是你應采用的做法:

lovablePets.addAll(Collections.nCopies(69, "fruit bat"));

通過使用 addAll(同時采用索引和一個 Collection作參數), 你可以將新的元素添加到一個 List 的中間,而不是末尾。

不可變單元素Set(Immutable Singleton Set)

有時你需要一個不可變的單元素 Set, 它由一個單一的特定元素所構成。Collections.singleton 方法可返回這樣一個 Set。這個實現的一個用途是以下這個慣用程序所表達的,它從一個 Collection中刪除了一個特定元素的所有具體值:

c.removeAll(Collections.singleton(e));

有一個相關的慣用程序,它從一個 Map 中刪除映射一個特定值的所有元素。例如,假設你有一個稱為 profession 的 Map ,他將人與他們所從事的工作相映射。假使你要刪除所有的律師,下面的程序可以完成這件事:

profession.values().removeAll(Collections.singleton(LAWYER));

這個實現的另一個用途是為接受Collection的方法提供一個單一輸入值。

空Set和空List常數

Collections 類提供兩個常數,用以表示空 Set 和空 List, 它們是Collections.EMPTY_SET和Collections.EMPTY_LIST。不清楚這兩個常數作為實現是否真的有資格,但本課程似乎是提及它們的最合適的地方。這兩個常數的主要用途是在你不想提供任何值時,將它們傳給需要Collection型參數的方法

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