文档

Java™教程
隐藏目录
包装器实现
路径: 集合类
课程: 实现

包装类实现

包装器实现将所有真正的工作委托给指定的集合,但在该集合提供的功能之上添加了额外的功能。对于设计模式爱好者来说,这是装饰者模式的一个例子。虽然它可能看起来有些奇特,但实际上非常简单明了。

这些实现是匿名的;库提供了一个静态工厂方法,而不是提供一个公共类。所有这些实现都在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);
}

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

Map<KeyType, ValType> m = Collections.synchronizedMap(new HashMap<KeyType, ValType>());
    ...
Set<KeyType> s = m.keySet();
    ...
// 在 m 上同步,而不是 s!
synchronized(m) {
    while (KeyType k : s)
        foo(k);
}

使用包装实现的一个小缺点是,您无法执行包装实现的任何非接口操作。因此,在上述List示例中,您无法在包装的ArrayList上调用ArrayListensureCapacity操作。

不可修改的包装器

与同步包装器不同,不可修改的包装器会减少功能。特别地,它们会拦截所有修改集合的操作,并抛出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);

Checked接口包装器

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


上一页: 双端队列实现
下一页: 方便实现