文档

Java™ 教程-Java Tutorials 中文版
包装器实现
Trail: Collections
Lesson: Implementations

包装器实现

包装器实现将所有实际工作委托给指定的集合,但在此集合提供的功能之上添加额外的功能。对于设计模式的粉丝,这是 decorator (装饰器) 模式的示例。虽然它看起来有点奇特,但它真的非常简单。

这些实现是匿名的;该库提供静态工厂方法,而不是提供公共类。所有这些实现都可以在 Collections 类中找到,它只包含静态方法。

同步包装器

同步包装器将自动同步(线程安全性)添加到任意集合。六个核心集合接口中的每一个 — CollectionSetListMapSortedSetSortedMap — 有一个静态工厂方法。

public static <T> Collection<T> synchronizedCollection(Collection<T> c);
public static <T> Set<T> synchronizedSet(Set<T> s);
public static <T> List<T> synchronizedList(List<T> list);
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m);
public static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s);
public static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m);

这些方法中的每一个都返回由指定集合支持的同步(线程安全)Collection。要保证串行访问,必须通过返回的集合完成对后备集合的 所有 访问。保证这一点的简单方法是不保留对支持集合的引用。使用以下技巧创建同步集合。

List<Type> list = Collections.synchronizedList(new ArrayList<Type>());

以这种方式创建的集合与正常同步的集合一样是线程安全的,例如 Vector

面对并发访问,用户必须在迭代时手动同步返回的集合。原因是迭代是通过对集合的多次调用来完成的,集合必须组成一个单独的原子操作。以下是迭代包装器同步集合的习惯用法。

Collection<Type> c = Collections.synchronizedCollection(myCollection);
synchronized(c) {
    for (Type e : c)
        foo(e);
}

如果使用显式迭代器,则必须从 synchronized 块中调用 iterator 方法。不遵循此建议可能会导致不确定的行为。迭代同步 MapCollection 视图的习惯用法是类似的。当迭代任何 Collection 视图时,用户必须在同步的 Map 上进行同步,而不是在 Collection 视图本身上进行同步,如下例所示。

Map<KeyType, ValType> m = Collections.synchronizedMap(new HashMap<KeyType, ValType>());
    ...
Set<KeyType> s = m.keySet();
    ...
// Synchronizing on m, not s!
synchronized(m) {
    while (KeyType k : s)
        foo(k);
}

使用包装器实现的一个小缺点是你无法执行包装实现的任何 noninterface (非接口) 操作。因此,例如,在前面的 List 示例中,你无法在包装上调用 ArrayListensureCapacity 操作 ArrayList

不可修改包装器

与为包装集合添加功能的同步包装器不同,不可修改的包装器可以消除功能。特别是,它们通过拦截将修改集合的所有操作并抛出 UnsupportedOperationException 来取消修改集合的能力。不可修改包装器有两个主要用途,如下所示:

与同步包装器一样,六个核心 Collection 接口中的每一个都有一个静态工厂方法。

public static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c);
public static <T> Set<T> unmodifiableSet(Set<? extends T> s);
public static <T> List<T> unmodifiableList(List<? extends T> list);
public static <K,V> Map<K, V> unmodifiableMap(Map<? extends K, ? extends V> m);
public static <T> SortedSet<T> unmodifiableSortedSet(SortedSet<? extends T> s);
public static <K,V> SortedMap<K, V> unmodifiableSortedMap(SortedMap<K, ? extends V> m);

检查接口包装器

提供了 Collections.checked interface (接口) 包装器以用于泛型集合。这些实现返回指定集合的​​dynamically (动态) 类型安全视图,如果客户端尝试添加错误类型的元素,则会抛出 ClassCastException。该语言中的泛型机制提供了编译时(静态)类型检查,但有可能打败这种机制。动态类型安全的视图完全消除了这种可能性。


Previous page: Deque Implementations
Next page: Convenience Implementations