Java 教程是为 JDK 8 编写的。本页中描述的示例和实践未利用在后续版本中引入的改进。
包装器实现将所有实际工作委托给指定的集合,但在此集合提供的功能之上添加额外的功能。对于设计模式的粉丝,这是 decorator (装饰器) 模式的示例。虽然它看起来有点奇特,但它真的非常简单。
这些实现是匿名的;该库提供静态工厂方法,而不是提供公共类。所有这些实现都可以在 Collections
类中找到,它只包含静态方法。
同步包装器将自动同步(线程安全性)添加到任意集合。六个核心集合接口中的每一个 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); }
使用包装器实现的一个小缺点是你无法执行包装实现的任何 noninterface (非接口) 操作。因此,例如,在前面的 List
示例中,你无法在包装上调用 ArrayList
的 ensureCapacity
操作 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
。该语言中的泛型机制提供了编译时(静态)类型检查,但有可能打败这种机制。动态类型安全的视图完全消除了这种可能性。