Java编程思想第4版[中文版](PDF格式)-第71部分
按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
对所有操作的支持。但是,如果想新建一个集合,同时不想为集合接口中的所有方法都提供有意义的定义,
同时令其仍与现有库配合,这种设计方法也确实提供了一个“后门”可以利用。
(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 《 length; i++) {
rnd = Math。abs(r。nextInt()) % src。length;
buf'i' = src'rnd';
}
return new String(buf);
}
// Create a random array of Strings:
public static
255
…………………………………………………………Page 257……………………………………………………………
String'' randStrings(int length; int size) {
String'' s = new String'size';
for(int i = 0; i 《 size; i++)
s'i' = randString(length);
return s;
}
public static void print(byte'' b) {
for(int i = 0; i 《 b。length; i++)
System。out。print(b'i' + 〃 〃);
System。out。println();
}
public static void print(String'' s) {
for(int i = 0; i 《 s。length; i++)
System。out。print(s'i' + 〃 〃);
System。out。println();
}
public static void main(String'' args) {
byte'' b = new byte'15';
r。nextBytes(b); // Fill with random bytes
print(b);
Arrays。sort(b);
print(b);
int loc = Arrays。binarySearch(b; b'10');
System。out。println(〃Location of 〃 + b'10' +
〃 = 〃 + loc);
// Test String sort & search:
String'' s = randStrings(4; 10);
print(s);
Arrays。sort(s);
print(s);
loc = Arrays。binarySearch(s; s'4');
System。out。println(〃Location of 〃 + s'4' +
〃 = 〃 + loc);
}
} ///:~
类的第一部分包含了用于产生随机字串对象的实用工具,可供选择的随机字母保存在一个字符数组中。
randString()返回一个任意长度的字串;而 readStrings()创建随机字串的一个数组,同时给定每个字串的
长度以及希望的数组大小。两个print()方法简化了对示范数组的显示。在 main()中,Random。nextBytes()
用随机选择的字节填充数组自变量(没有对应的Random 方法用于创建其他基本数据类型的数组)。获得一个
数组后,便可发现为了执行sort()或者 binarySearch(),只需发出一次方法调用即可。与binarySearch()
有关的还有一个重要的警告:若在执行一次binarySearch()之前不调用 sort(),便会发生不可预测的行为,
其中甚至包括无限循环。
对String 的排序以及搜索是相似的,但在运行程序的时候,我们会注意到一个有趣的现象:排序遵守的是字
典顺序,亦即大写字母在字符集中位于小写字母的前面。因此,所有大写字母都位于列表的最前面,后面再
跟上小写字母——Z 居然位于a 的前面。似乎连电话簿也是这样排序的。
2。 可比较与比较器
但假若我们不满足这一排序方式,又该如何处理呢?例如本书后面的索引,如果必须对以A 或a 开头的词条
分别到两处地方查看,那么肯定会使读者颇不耐烦。
若想对一个 Object 数组进行排序,那么必须解决一个问题。根据什么来判定两个 Object 的顺序呢?不幸的
是,最初的 Java 设计者并不认为这是一个重要的问题,否则就已经在根类 Object 里定义它了。这样造成的
256
…………………………………………………………Page 258……………………………………………………………
一个后果便是:必须从外部进行Object 的排序,而且新的集合库提供了实现这一操作的标准方式(最理想的
是在Object 里定义它)。
针对Object 数组(以及 String,它当然属于Object 的一种),可使用一个 sort(),并令其接纳另一个参
数:实现了 parator 接口(即“比较器”接口,新集合库的一部分)的一个对象,并用它的单个
pare()方法进行比较。这个方法将两个准备比较的对象作为自己的参数使用——若第一个参数小于第二
个,返回一个负整数;若相等,返回零;若第一个参数大于第二个,则返回正整数。基于这一规则,上述例
子的String 部分便可重新写过,令其进行真正按字母顺序的排序:
//: Alphap。java
// Using parator to perform an alphabetic sort
package c08。newcollections;
import java。util。*;
public class Alphap implements parator {
public int pare(Object o1; Object o2) {
// Assume it's used only for Strings。。。
String s1 = ((String)o1)。toLowerCase();
String s2 = ((String)o2)。toLowerCase();
return s1。pareTo(s2);
}
public static void main(String'' args) {
String'' s = Array1。randStrings(4; 10);
Array1。print(s);
Alphap ac = new Alphap();
Arrays。sort(s; ac);
Array1。print(s);
// Must use the parator to search; also:
int loc = Arrays。binarySearch(s; s'3'; ac);
System。out。println(〃Location of 〃 + s'3' +
〃 = 〃 + loc);
}
} ///:~
通过造型为 String,pare()方法会进行“暗示”性的测试,保证自己操作的只能是String 对象——运行
期系统会捕获任何差错。将两个字串都强迫换成小写形式后,String。pareTo()方法会产生预期的结果。
若用自己的 parator 来进行一次 sort(),那么在使用binarySearch()时必须使用那个相同的
parator。
Arrays 类提供了另一个 sort()方法,它会采用单个自变量:一个 Object 数组,但没有parator。这个
sort()方法也必须用同样的方式来比较两个 Object。通过实现parable 接口,它采用了赋予一个类的
“自然比较方法”。这个接口含有单独一个方法——pareTo(),能分别根据它小于、等于或者大于自变量
而返回负数、零或者正数,从而实现对象的比较。下面这个例子简单地阐示了这一点:
//: pClass。java
// A class that implements parable
package c08。newcollections;
import java。util。*;
public class pClass implements parable {
private int i;
public pClass(int ii) { i = ii; }
public int pareTo(Object o) {
// Implicitly tests for correct type:
257
…………………………………………………………Page 259……………………………………………………………
int argi = ((pClass)o)。i;
if(i == argi) return 0;
if(i 《 argi) return …1;
return 1;
}
public static void print(Object'' a) {
for(int i = 0; i 《 a。length; i++)
System。out。print(a'i' + 〃 〃);
System。out。println();
}
public String toString() { return i + 〃〃; }
public static void main(String'' args) {
pClass'' a = new pClass'20';
for(int i = 0; i 《 a。length; i++)
a'i' = new pClass(
(int)(Math。random() *100));
print(a);
Arrays。sort(a);
print(a);
int loc = Arrays。binarySearch(a; a'3');
System。out。println(〃Location of 〃 + a'3' +
〃 = 〃 + loc);
}
} ///:~
当然,我们的 pareTo()方法亦可根据实际情况增大复杂程度。
3。 列表
可用与数组相同的形式排序和搜索一个列表(List )。用于排序和搜索列表的静态方法包含在类
Collections 中,但它们拥有与Arrays 中差不多的签名:sort(List)用于对一个实现了 parable 的对象
列表进行排序;binarySearch(List;Object)用于查找列表中的某个对象;sort(List;parator)利用一个
“比较器”对一个列表进行排序;而binarySearch(List;Object;parator)则用于查找那个列表中的一个
对象(注释⑨)。下面这个例子利用了预先定义好的pClass 和 Alphap 来示范 Collections 中的各种
排序工具:
//: ListSort。java
// Sorting and searching Lists with 'Collections'
package c08。newcollections;
import java。util。*;
public class ListSort {
public static void main(String'' args) {
final int SZ = 20;
// Using 〃natural parison method〃:
List a = new ArrayList();
for(int i = 0; i 《 SZ; i++)
a。add(new pClass(
(int)(Math。random() *100)));
Collection1。print(a);
Collections。sort(a);
Collection1。print(a);
Object find = a。get(SZ/2);
258
…………………………………………………………Page 260……………………………………………………………
int loc = Collections。binarySearch(a; find);
System。out。println(〃Location of 〃 + find +
〃 = 〃 + loc);
// Using a parator:
List b = new ArrayList();
for(int i = 0; i 《 SZ; i++)
b。add(Array1。randString(4));
Collection1。print(b);
Alphap ac = new Alphap();
Collections。sort(b; ac);
Collection1。print(b);
find = b。get(SZ/2);
// Must use the parator to search; also:
loc = Collections。binarySearch(b; find; ac);
System。out。println(〃Location of 〃 + find +
〃 = 〃 + loc);
}
} ///:~
⑨:在本书写作时,已宣布了一个新的Collections。stabl