Chinaunix首页 | 论坛 | 博客
  • 博客访问: 16493665
  • 博文数量: 5645
  • 博客积分: 9880
  • 博客等级: 中将
  • 技术积分: 68081
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-28 13:35
文章分类

全部博文(5645)

文章存档

2008年(5645)

我的朋友

分类:

2008-04-28 21:45:16

下载本文示例代码
  JDK 5.0 中最吸引人的地方在于集合框架的一些最突出的特性上,例如:支持泛型的语言级别上的新变化,以及可以在 java.util.concurrent 包中找到的并发集合工具包。在本文中,我将研究其他三个变化:更新过的 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 的程序所示: 清单 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()  其中 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 的用法 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(),并发集合是比纯粹的包装器更好的选择。其他方法则被认为不是必需的。也许新版本中会添加 checkedQueue()(和 checkedBlockingQueue()) 。   JDK 5.0 中最吸引人的地方在于集合框架的一些最突出的特性上,例如:支持泛型的语言级别上的新变化,以及可以在 java.util.concurrent 包中找到的并发集合工具包。在本文中,我将研究其他三个变化:更新过的 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 的程序所示: 清单 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()  其中 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 的用法 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(),并发集合是比纯粹的包装器更好的选择。其他方法则被认为不是必需的。也许新版本中会添加 checkedQueue()(和 checkedBlockingQueue()) 。 下载本文示例代码


驯服Tiger(J2SE5.0)之集合框架驯服Tiger(J2SE5.0)之集合框架驯服Tiger(J2SE5.0)之集合框架驯服Tiger(J2SE5.0)之集合框架驯服Tiger(J2SE5.0)之集合框架驯服Tiger(J2SE5.0)之集合框架驯服Tiger(J2SE5.0)之集合框架驯服Tiger(J2SE5.0)之集合框架驯服Tiger(J2SE5.0)之集合框架驯服Tiger(J2SE5.0)之集合框架驯服Tiger(J2SE5.0)之集合框架驯服Tiger(J2SE5.0)之集合框架驯服Tiger(J2SE5.0)之集合框架驯服Tiger(J2SE5.0)之集合框架驯服Tiger(J2SE5.0)之集合框架
阅读(573) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~