驯服Tiger – 荟萃框架
副标题#e#
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)
#p#副标题#e#
自从荟萃框架初次呈此刻 J2SE 1.2 中以来,人们第一次对实用东西类举办 了变动。我无法确定为什么 Sun 要等这么久才举办变动,可是对付可用的辅佐 器要领系列来说,这些变动是受接待的添加。
新添加的第一个要领是 hashCode()。对付任意数组范例,都可以挪用 Arrays.hashCode(arrayVar) 要领来得到名目精采的哈希码。这个哈希码可以用 作 HashMap 可能其他相关目标的键。假如您不知道如何生成精采的哈希码,那 么最好利用 Arrays 类,它能发生更少斗嘴。Arrays 类生成等价于拥有沟通元 素的 List 的代码。
在建设本身的类时,既需要提供 equals() 要领,又需要提供 hashCode() 要领。在 Arrays 的新要领 hashCode() 的辅佐下,可觉得任何当地数组范例生 成哈希码,而不消在每次需要它的时候折腾您本身。
所有数组范例都可用的另一个要领是 toString()。对付任何数组范例,都可 以挪用 Arrays.toString(arrayVar) 得到逗号脱离的元素列表,列表用方括号 困绕,如清单 1 的措施所示:
清单 1. 用 Arrays.toString 生成字符串
import java.util.Arrays;
public class ArgsToString {
public static void main(String args[]) {
System.out.println(Arrays.toString(args));
}
}
清单 2 显示了功效:
清单 2. 清单 1 的功效
>java ArgsToString One Two Three
[One, Two, Three]
新的 deepEquals()、deepHashCode() 和 deepToString() 要领的事情方法 雷同于它们那些非深度(non-deep)的同类,但它们不只会停下手来处理惩罚顶级数 组的每个元素,还会更深入地研究生成功效的多维数组。
固然不是一个新要领,但 asList() 要领在 5.0 的事情方法有所差异。以前 ,这个要领接管 Object[] 数组作为它的参数。此刻,因为 Tiger 的可变参数 列表特性,任何用逗号脱离的列表都可以接管,如清单 3 所示:
清单 3. Arrays.asList 的区别
import java.util.Arrays;
public class AsList {
public static void main(String args[]) {
// Before
List before = Arrays.asList(args);
// After
List after = Arrays.asList("One", "Two", "Three");
}
}
假如通报给呼吁行的元素差异,清单 3 中的两个示例没须要发生同样的功效 ,可是它确实展示了 Tiger 在语言级别上的变革如何扩展了 Arrays 原有的 asList() 要领。
荟萃
Arrays 用于处理惩罚差异荟萃的帮助类是 Collections 类。同样,这个类也不 是一个新类,可是该类的特性已经针对 5.0 作了扩展。此刻有 13 个新要领:
checkedCollection()
checkedSet()
checkedSortedSet()
checkedList()
checkedMap()
checkedSortedMap()
emptySet()
emptyList()
emptyMap()
reverseOrder()
frequency()
disjoint()
addAll()
#p#分页标题#e#
个中 6 个 checked*() 要领事情起来与 6 个 synchronized*() 和 unmodifiable*() 要领雷同。利用 synchronized*() 要领时,要向该要领提供 一个荟萃,然后该要领将返回同一个荟萃的同步的、线程安详的版本。利用 unmodifiable*() 要领时,获得的是指定荟萃的只读视图。除了荟萃参数之外, checked*() 操纵大概还要求第二个可能第三个参数(如清单 4 所示),并返回 该荟萃的动态的范例安详视图:
清单 4. 检测后的荟萃
public static <E> Collection<E> checkedCollection(
Collection<E> c, Class<E> type)
public static <E> Set<E> checkedSet(
Set<E> s, Class<E> type)
public static <E> SortedSet<E> checkedSortedSet(
SortedSet<E> s, Class<E> type)
public static <E> List<E> checkedList(
List<E> list, Class<E> type)
public static <K,V> Map<K,V> checkedMap(
Map<K,V> m, Class<K> keyType, Class<V> valueType)
public static <K,V> SortedMap<K,V> checkedSortedMap (
SortedMap<K,V> m, Class<K> keyType, Class<V> valueType)
利用 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 个要领:
清单 5. Queue 接口
public boolean offer(Object element)
public Object remove()
public Object poll()
public Object element()
public Object peek()
请记着,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 接口,那么就 会发生运行时错误:
清单 6. PriorityQueue 结构函数
PriorityQueue()
PriorityQueue(Collection<? extends E> c)
PriorityQueue(int initialCapacity)
PriorityQueue(int initialCapacity, Comparator<? super E> comparator)
PriorityQueue(PriorityQueue<? extends E> c)
PriorityQueue(SortedSet<? extends E> c)
为了演示 PriorityQueue 的用法,清单 7 中的措施添加了所有呼吁行元素 ,并按字母顺序处理惩罚它们。由于行列布局是 LinkedList,所以顺序该当是典范 的 FIFO 顺序,可是 PriorityQueue 将按照优先级对元素举办排序:
清单 7. PriorityQueue 的用法
#p#分页标题#e#
import java.util.*;
import java.util.concurrent.*;
public class Priority {
public static void main(String args[]) {
Queue<String> queue =
new PriorityQueue<String>(Arrays.asList(args));
String element;
while ((element = queue.poll()) != null) {
System.out.println(element);
}
}
}
清单 8 显示了用呼吁行 one two three four 运行措施之后的输出 :
清单 8. 清单 7 的功效
>java Priority one two three four
four
one
three
two
关于新的 Queue 接口,有件事需要提一下,这件事与 Collections 类有关 :要领 checkedQueue()、emptyQueue()、synchronizedQueue() 和 unmodifiableQueue() 全都是 Collections 类中所缺少的。按照 bug 陈诉,除 了 checkedQueue() 之外,所有类都是存心缺失的。对付 synchronizedQueue() ,并发荟萃是比纯粹的包装器更好的选择。其他要领例被认为不是必须的。也许 Tiger/6.0 版本中会添加 checkedQueue()(和 checkedBlockingQueue()) 。
本文配套源码