JDK 5.0 中最吸引人的地方在于集合框架的一些最突出的特性上,例如:支持泛型的語言級別上的新變化,以及可以在 java.util.concurrent
包中找到的并發集合工具包。實際上,以前在 developerWorks 上的“馴服 Tiger: 并發集合”和“介紹 JDK 5.0 中的泛型”這兩篇教程中介紹了上述特性。但是其他增強還沒有得到足夠的重視。在本文中,我將研究其他三個變化:更新過的 Arrays
和 Collections
類、新的 Queue
接口以及它的 PriorityQueue
實現。
數組(Array)
Arrays
類提供了一系列處理數組的靜態工具方法,這些索引的數據結構的大小是固定的。在 5.0 版本之前,Arrays
類擁有針對原始數據庫類型和通用 Object
類型的每種不同數組類型的 binarySearch()
、equals()
、fill()
和 sort()
方法。用于將 Object
數組轉換成 List
的附加 asList()
方法仍然有用。Tiger 為所有數組添加了 hashCode()
和 toString()
方法,還添加了特定于 Object
數組的 deepEquals()
、deepHashCode()
和 deepToString()
方法??傆嬘?21 個新方法可用:
public static boolean deepEquals(Object[] a1, Object[] a2)
public static int deepHashCode(Object[] a)
public static String deepToString(Object[] a)
public static int hashCode(boolean[] a)
public static int hashCode(byte[] a)
public static int hashCode(char[] a)
public static int hashCode(double[] a)
public static int hashCode(float[] a)
public static int hashCode(int[] a)
public static int hashCode(long[] a)
public static int hashCode(Object[] a)
public static int hashCode(short[] a)
public static String toString(boolean[] a)
public static String toString(byte[] a)
public static String toString(char[] a)
public static String toString(double[] a)
public static String toString(float[] a)
public static String toString(int[] a)
public static String toString(long[] a)
public static String toString(Object[] a)
public static String toString(short[] a)
自從集合框架初次出現在 J2SE 1.2 中以來,人們第一次對實用工具類進行了更改。我無法確定為什么 Sun 要等這么久才進行更改,但是對于可用的幫助器方法系列來說,這些更改是受歡迎的添加。
新添加的第一個方法是 hashCode()
。對于任意數組類型,都可以調用 Arrays.hashCode(arrayVar)
方法來獲得格式良好的哈希碼。這個哈希碼可以用作 HashMap
或者其他相關目的的鍵。如果您不知道如何生成良好的哈希碼,那么最好使用 Arrays
類,它能產生更少沖突。Arrays 類生成等價于擁有相同元素的 List
的代碼。
在創建自己的類時,既需要提供 equals()
方法,又需要提供 hashCode()
方法。在 Arrays
的新方法 hashCode()
的幫助下,可以為任何本地數組類型生成哈希碼,而不用在每次需要它的時候折騰您自己。
所有數組類型都可用的另一個方法是 toString()
。對于任何數組類型,都可以調用 Arrays.toString(arrayVar)
獲得逗號分隔的元素列表,列表用方括號包圍,如清單 1 的程序所示:
|
清單 2 顯示了結果:
|
新的 deepEquals()
、deepHashCode()
和 deepToString()
方法的工作方式類似于它們那些非深度(non-deep)的同類,但它們不僅會停下手來處理頂級數組的每個元素,還會更深入地研究生成結果的多維數組。
雖然不是一個新方法,但 asList()
方法在 5.0 的工作方式有所不同。以前,這個方法接受 Object[]
數組作為它的參數?,F在,因為 Tiger 的可變參數列表特性,任何用逗號分隔的列表都可以接受,如清單 3 所示:
|
如果傳遞給命令行的元素不同,清單 3 中的兩個示例沒必要產生同樣的結果 ,但是它確實展示了 Tiger 在語言級別上的變化如何擴展了 Arrays
原有的 asList()
方法。
![]() |
|
集合
Arrays
用于處理不同集合的輔助類是 Collections
類。同樣,這個類也不是一個新類,但是該類的特性已經針對 5.0 作了擴展?,F在有 13 個新方法:
checkedCollection()
checkedSet()
checkedSortedSet()
checkedList()
checkedMap()
checkedSortedMap()
emptySet()
emptyList()
emptyMap()
reverseOrder()
frequency()
disjoint()
addAll()
其中 6 個 checked*()
方法工作起來與 6 個 synchronized*()
和 unmodifiable*()
方法類似。使用 synchronized*()
方法時,要向該方法提供一個集合,然后該方法將返回同一個集合的同步的、線程安全的版本。使用 unmodifiable*()
方法時,得到的是指定集合的只讀視圖。除了集合參數之外,checked*()
操作可能還要求第二個或者第三個參數(如清單 4 所示),并返回該集合的動態的類型安全視圖:
|
使用 Java 5.0 平臺,您可能以為:由于將集合聲明為通用集合 (Collection<String> c = new HashSet<String>();
),所以不需要進行運行時檢測了。但是如果向工具方法傳遞 String
版本的 HashSet
,而工具方法只能處理非通用的 Set
,那么該方法可能就會錯誤地向集合添加一個非 String
元素。通過臨時修改程序,用 Collection<String> c = Collections.checkedCollection(new HashSet<String>(), String.class);
添加運行時檢查,您可以迅速發現問題的根源。
三個 empty*()
方法 —— emptySet()
、emptyList()
和 emptyMap()
—— 生成空的不可改變的集合。雖然也可以用 new ArraySet()
這樣的方法創建空集合,但是還要通過某個 unmodifiable*()
方法才能確保新集合是不可改變的。empty 方法用更理想的方式提供了空的只讀集合。
![]() |
|
隊列(Queue)接口
5.0 集合框架較大的一個改變就是添加了新的基接口 Queue
。雖然這個接口是在“并發集合”技巧 (請參閱 參考資料)中描述的,但它的應用并不限于并發。在計算機科學中,隊列數據結構是基本的先進先出(FIFO) 結構。項目添加到尾部,并且要從頂部刪除。不僅能添加和刪除元素,還能查看隊列中有哪些元素。清單 5 顯示了 Queue
接口的 5 個方法:
|
請記住,Queue
是從 Collection
接口擴展的,所以實現 Queue
接口也就實現了 Collection
。在使用 Queue
的實現時,應當將自己限制在接口的方法上。例如,向 Queue
添加元素可以用 Collection
的 add()
方法來實現,它在失敗時會拋出未檢測異常。相反,如果大小有限的隊列滿了,那么 offer()
方法會返回 false
,而不需要處理隊列滿的異常。
java.util.concurrent
包中具有 Queue
接口的多個實現,但并不包含所有實現。LinkedList
類針對 JDK 5.0 的 Queue
接口作了修正,而 PriorityQueue
是隨 JDK 5.0 添加進來的。余下的實現 —— ArrayBlockingQueue
、ConcurrentLinkedQueue
、DelayQueue
、LinkedBlockingQueue
、PriorityBlockingQueue
和 SynchronousQueue
—— 都是 java.util.concurrent
包的組成部分。
因為 LinkedList
不是新事物,所以我們來看一下新的 PriorityQueue
類。如清單 6 所示,可以用 6 種方法創建它。在不能使用 Comparator
時,可以使用元素的自然順序來確定優先級。如果元素沒有實現 Comparable
接口,那么就會產生運行時錯誤:
|
為了演示 PriorityQueue
的用法,清單 7 中的程序添加了所有命令行元素,并按字母順序處理它們。由于隊列結構是 LinkedList
,所以順序應當是典型的 FIFO 順序,但是 PriorityQueue
將根據優先級對元素進行排序:
|
清單 8 顯示了用命令行 one two three four
運行程序之后的輸出 :
|
關于新的 Queue
接口,有件事需要提一下,這件事與 Collections
類有關:方法 checkedQueue()
、emptyQueue()
、synchronizedQueue()
和 unmodifiableQueue()
全都是 Collections
類中所缺少的。根據 bug 報告,除了 checkedQueue()
之外,所有類都是故意缺失的。對于 synchronizedQueue()
,并發集合是比純粹的包裝器更好的選擇。其他方法則被認為不是必需的。也許 Tiger/6.0 版本中會添加 checkedQueue()
(和 checkedBlockingQueue()
) 。
原文轉自:http://www.anti-gravitydesign.com