该Java教程是针对JDK 8编写的。本页面中描述的示例和实践不利用后续版本引入的改进,并可能使用不再可用的技术。
请参阅Java语言更改了解Java SE 9及其后续版本中更新的语言特性的摘要。
请参阅JDK发行说明了解有关所有JDK版本的新功能、增强功能和已删除或弃用选项的信息。
包装器实现将所有真正的工作委托给指定的集合,但在该集合提供的功能之上添加了额外的功能。对于设计模式爱好者来说,这是装饰者模式的一个例子。虽然它可能看起来有些奇特,但实际上非常简单明了。
这些实现是匿名的;库提供了一个静态工厂方法,而不是提供一个公共类。所有这些实现都在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); }
如果使用显式迭代器,则必须在同步块中调用iterator
方法。不遵循此建议可能导致非确定性行为。在迭代同步Map
的Collection
视图时,遵循类似的模式。在迭代其任何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
上调用ArrayList
的ensureCapacity
操作。
与同步包装器不同,不可修改的包装器会减少功能。特别地,它们会拦截所有修改集合的操作,并抛出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
接口包装器是为了与泛型集合一起使用而提供的。这些实现返回指定集合的动态类型安全视图,如果客户端尝试添加错误类型的元素,则会抛出ClassCastException
异常。语言中的泛型机制提供了编译时(静态)类型检查,但是有可能会绕过该机制。动态类型安全视图完全消除了这种可能性。