按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
果需要创建大量Map,而且只有在以后才需要涉及大量检索操作,那么最佳的策略就是:创建和填充
TreeMap;以后检索量增大的时候,再将重要的TreeMap 转换成HashMap——使用HashMap(Map)构建器。同样
地,只有在事实证明确实存在性能瓶颈后,才应关心这些方面的问题——先用起来,再根据需要加快速度。
8。7。6 未支持的操作
利用 static (静态)数组Arrays。toList(),也许能将一个数组转换成List,如下所示:
//: Unsupported。java
// Sometimes methods defined in the Collection
// interfaces don't work!
package c08。newcollections;
import java。util。*;
public class Unsupported {
private static String'' s = {
253
…………………………………………………………Page 255……………………………………………………………
〃one〃; 〃two〃; 〃three〃; 〃four〃; 〃five〃;
〃six〃; 〃seven〃; 〃eight〃; 〃nine〃; 〃ten〃;
};
static List a = Arrays。toList(s);
static List a2 = Arrays。toList(
new String'' { s'3'; s'4'; s'5' });
public static void main(String'' args) {
Collection1。print(a); // Iteration
System。out。println(
〃a。contains(〃 + s'0' + 〃) = 〃 +
a。contains(s'0'));
System。out。println(
〃a。containsAll(a2) = 〃 +
a。containsAll(a2));
System。out。println(〃a。isEmpty() = 〃 +
a。isEmpty());
System。out。println(
〃a。indexOf(〃 + s'5' + 〃) = 〃 +
a。indexOf(s'5'));
// Traverse backwards:
ListIterator lit = a。listIterator(a。size());
while(lit。hasPrevious())
System。out。print(lit。previous());
System。out。println();
// Set the elements to different values:
for(int i = 0; i 《 a。size(); i++)
a。set(i; 〃47〃);
Collection1。print(a);
// piles; but won't run:
lit。add(〃X〃); // Unsupported operation
a。clear(); // Unsupported
a。add(〃eleven〃); // Unsupported
a。addAll(a2); // Unsupported
a。retainAll(a2); // Unsupported
a。remove(s'0'); // Unsupported
a。removeAll(a2); // Unsupported
}
} ///:~
从中可以看出,实际只实现了 Collection 和 List 接口的一部分。剩余的方法导致了不受欢迎的一种情况,
名为UnsupportedOperationException。在下一章里,我们会讲述违例的详细情况,但在这里有必要进行一
下简单说明。这里的关键在于“集合接口”,以及新集合库内的另一些接口,它们都包含了“可选的”方
法。在实现那些接口的集合类中,或者提供、或者没有提供对那些方法的支持。若调用一个未获支持的方
法,就会导致一个UnsupportedOperationException (操作未支持违例),这表明出现了一个编程错误。
大家或许会觉得奇怪,不是说“接口”和基础类最大的“卖点”就是它们许诺这些方法能产生一些有意义的
行为吗?上述违例破坏了那个许诺——它调用的一部分方法不仅不能产生有意义的行为,而且还会中止程序
的运行。在这些情况下,类型的所谓安全保证似乎显得一钱不值!但是,情况并没有想象的那么坏。通过
Collection,List,Set 或者Map,编译器仍然限制我们只能调用那个接口中的方法,所以它和 Smalltalk 还
是存在一些区别的(在 Smalltalk 中,可为任何对象调用任何方法,而且只有在运行程序时才知道这些调用
是否可行)。除此以外,以Collection 作为自变量的大多数方法只能从那个集合中读取数据——Collection
的所有“read ”方法都不是可选的。
这样一来,系统就可避免在设计期间出现接口的冲突。而在集合库的其他设计方案中,最终经常都会得到数
254
…………………………………………………………Page 256……………………………………………………………
量过多的接口,用它们描述基本方案的每一种变化形式,所以学习和掌握显得非常困难。有些时候,甚至难
于捕捉接口中的所有特殊情况,因为人们可能设计出任何新接口。但 Java 的“不支持的操作”方法却达到了
新集合库的一个重要设计目标:易于学习和使用。但是,为了使这一方法真正有效,却需满足下述条件:
(1) UnsupportedOperationException必须属于一种“非常”事件。也就是说,对于大多数类来说,所有操
作都应是可行的。只有在一些特殊情况下,一、两个操作才可能未获支持。新集合库满足了这一条件,因为
绝大多数时候用到的类——ArrayList,LinkedList,HashList 和 HashMap,以及其他集合方案——都提供了
对所有操作的支持。但是,如果想新建一个集合,同时不想为集合接口中的所有方法都提供有意义的定义,
同时令其仍与现有库配合,这种设计方法也确实提供了一个“后门”可以利用。
(2) 若一个操作未获支持,那么UnsupportedOperationException (未支持的操作违例)极有可能在实现期
间出现,则不是在产品已交付给客户以后才会出现。它毕竟指出的是一个编程错误——不正确地使用了一个
类。这一点不能十分确定,通过也可以看出这种方案的“试验”特征——只有经过多次试验,才能找出最理
想的工作方式。
在上面的例子中,Arrays。toList()产生了一个 List (列表),该列表是由一个固定长度的数组后推出来
的。因此唯一能够支持的就是那些不改变数组长度的操作。在另一方面,若请求一个新接口表达不同种类的
行为(可能叫作“FixedSizeList ”——固定长度列表),就有遭遇更大的复杂程度的危险。这样一来,以后
试图使用库的时候,很快就会发现自己不知从何处下手。
对那些采用 Collection,List,Set 或者Map 作为参数的方法,它们的文档应当指出哪些可选的方法是必须
实现的。举个例子来说,排序要求实现set()和 Iterator。set()方法,但不包括add()和 remove() 。
8。7。7 排序和搜索
Java 1。2 添加了自己的一套实用工具,可用来对数组或列表进行排列和搜索。这些工具都属于两个新类的
“静态”方法。这两个类分别是用于排序和搜索数组的Arrays,以及用于排序和搜索列表的Collections。
1。 数组
Arrays 类为所有基本数据类型的数组提供了一个过载的 sort()和 binarySearch(),它们亦可用于String 和
Object。下面这个例子显示出如何排序和搜索一个字节数组(其他所有基本数据类型都是类似的)以及一个
String 数组:
//: Array1。java
// Testing the sorting & searching in Arrays
package c08。newcollections;
import java。util。*;
public class Array1 {
static Random r = new Random();
static String ssource =
〃ABCDEFGHIJKLMNOPQRSTUVWXYZ〃 +
〃abcdefghijklmnopqrstuvwxyz〃;
static char'' src = ssource。toCharArray();
// Create a random String
public static String randString(int length) {
char'' buf = new char'length';
int rnd;
for(int i = 0; i 《 len