为满足编程的需求,Collection 和 Map 有多种不同的实现。
与持有对象有关的接口是 Collection,List,Set 和 Map。最理想的情况是,你的代码只
与这些接口打交道,仅在创建容器的时候说明容器的特定类型。因此可以这样创建一个 List:
List x = new LinkedList();
当然,你可以将x 定义为 LinkedList(代替通用的 List),使 x 带有明确的类型信息。接
口的优美之处(或者说目的)在于,如果你决定改变当前的实现,只需要在创建的位置做
些修改即可,就像这样:
List x = new ArrayList();
而其它代码则无需改动(迭代器也能实现部分通用性)。
在容器类层次结构图中,可以看到有许多以”Abstract”开头的名字,这有点令人迷惑。其
实它们只是部分实现了某个特定接口的简单工具而已。举个例子,如果要制作自己的 Set,
一般不会直接继承Set 接口,然后实现所有的方法。而是应该继承 AbstractSet,只为自
己的新类作最必要的工作。不过,容器类类库已经包含足够的功能来满足你的需要了。所
以,对我们而言,可以忽略那些以”Abstract”开头的类。
因此,再看上图时,我们只关心顶层的接口和“具体类”(由实线方框表示)。典型情况
是你会生成一个“具体类”的对象,然后将它向上转型为对应的接口,在代码中使用接口
操作它。此外,新的程序不需要使用过时的容器。注意,WeakHashMap
和 JDK 1.4 中的 IdentityHashMap 没有包含在图中,因为它们是有特殊用途的工具,很
少会用到。
下面是个简单的例子,使用 String 对象填充 Collection(使用的是 ArrayList),并且打
印 Collection 中的每个元素:
//:c11:SimpleCollection.java
// A simpleexample using Java 2 Collections.
import com.bruceeckel.simpletest.*;
import java.util.*;
public class SimpleCollection {
private static Test monitor = new Test();
public static void main(String[] args) {
// Upcastbecause we just want to
// work withCollection features
Collection c = new ArrayList();
for(int i = 0; i < 10; i++)
c.add(Integer.toString(i));
Iterator it = c.iterator();
while(it.hasNext())
System.out.println(it.next());
monitor.expect(new String[] {
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9"
});
}
} ///:~
main()中第一行代码生成一个 ArrayList 对象,并向上类型转换为 Collection。因为此例
只用到了Collection 的方法,所以任何 Collection 子类的对象都能工作,不过 ArrayList
是最常用的Collection。
方法 add()正如其名,其功能是将新元素添加到 Collection 中。不过说明文档更谨慎地对
add()做出了定义:“确保容器包含特定的元素”。这是考虑到了 Set 的含义,它不添加重
复元素。对于ArrayList,或者任意的 List,方法 add()都表示“将元素存入容器”,因为
List 不在乎元素是否重复。
所有的 Collection 都能通过 iterator()方法生成 Iterator。此例生成了一个 Iterator,用
来遍历 Collection 并打印每个元素。