Wrapper实现将所有实际工作委托给指定的集合,但在此集合提供的功能之上添加了额外的功能。对于设计模式爱好者,这是装饰器模式的示例。尽管它看起来有些奇特,但确实非常简单。
这些实现是匿名的。该库提供了一个静态工厂方法,而不是提供公共类。所有这些实现都可以在Collections
类中找到,该类仅由静态方法组成。
同步Wrapper
同步Wrapper将自动同步(线程安全)添加到任意集合。六个核心集合接口—— Collection
, Set
, List
, Map
, SortedSet
和 SortedMap
——每个都有一个静态的工厂方法。
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
方法。不遵循此建议可能导致不确定的行为。遍历同步Map
的Collection
视图的惯用法是相似的。如下面的示例所示,当用户在其任何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);
}
使用包装器实现的一个小缺点是您无法执行包装器实现的任何非接口操作。因此,例如,在前面的List
示例中,您无法在包装的ArrayList
上调用ArrayList
的 ensureCapacity
操作。
不可修改的Wrapper
与为包装的集合添加功能的同步包装不同,不可修改的包装会删除功能。特别是,它们通过拦截所有将修改集合的操作并抛出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);
已检查的接口Wrapper
提供了Collections.checked
接口包装器,以与泛型集合一起使用。这些实现返回指定集合的动态类型安全视图,如果客户端尝试添加错误类型的元素,则该视图将抛出ClassCastException
。该语言中的泛型机制提供了编译时(静态)类型检查,但是有可能破坏这种机制。动态类型安全视图完全消除了这种可能性。