在介绍完Collections框架的各个接口之后,下面我们来看一下各接口都有哪些具体的实现类,以及他们的用途。
实现类按照可以分成如下几类:
- General-purpose implementations are the most commonly used
implementations, designed for everyday use. They are summarized in the table
below.
- Special-purpose implementations are designed for use in special
situations and display nonstandard performance characteristics, usage
restrictions, or behavior.
- Concurrent implementations are designed to support high concurrency,
typically at the expense of single-threaded performance. These implementations
are part of the
java.util.concurrent
package.
- Wrapper implementations are used in combination with other types of
implementations, often the general-purpose ones, to provide added or restricted
functionality.
- Convenience implementations are mini-implementations, typically made
available via static factory methods, that provide convenient, efficient
alternatives to general-purpose implementations for special collections (for
example, singleton sets).
- Abstract implementations are skeletal implementations that facilitate
the construction of custom implementations — described later in the Custom Collection Implementations section. An advanced topic,
it's not particularly difficult, but relatively few people will need to do it.
我们先来总结一下general-purpose的实现类:
General-purpose
Implementations
Interfaces |
Implementations |
|
Hash table |
Resizable array |
Tree |
Linked list |
Hash table + Linked list |
Set |
HashSet |
|
TreeSet |
|
LinkedHashSet |
List |
|
ArrayList |
|
LinkedList |
|
Queue |
|
|
|
LinkedList |
|
Map |
HashMap |
|
TreeMap |
|
LinkedHashMap |
注意LinkedList同时实现了List和Queue两种接口。
下表是gegeneral-purpose implementations、special-purpose implementations和concurrent implementations的总结:
Interfaces |
gegeneral-purpose |
special-purpose |
concurrent
|
Set |
HashSet
TreeSet
LinkedHashSet
|
EnumSet
CopyOnWriteArraySet
|
|
List |
ArrayList
LinkedList
|
CopyOnWriteArrayList |
|
Queue |
LinkedList
PriorityQueue
|
|
LinkedBlockingQueue
ArrayBlockingQueue
PriorityBlockingQueue
DelayQueue
SynchronousQueue
|
Map |
HashMap
TreeMap
LinkedHashMap
|
EnumMap
WeakHashMap
IdentityHashMap
|
ConcurrentHashMap |
1. Set实现类
Set有三种general-purpose的实现类,HashSet、TreeSet和LinkedHashSet。其中HashSet速度最快(多数操作都是常数时间),TreeSet(多数操作都是log级时间),但TreeSet有序。LinkedHashSet能提供按照插入顺序排列的遍历,他的速度接近于HashSet,但空间消耗稍大(hash table + linked list)。
HashSet和LinkedHashSet都能在构造函数中指定初始的capacity,和load factor,而TreeSet使不能的。
有一点需要注意的是,HashSet的遍历时间是与它自身的容量大小(而不是储存的元素个数)成正比的(线性关系)。因此,如果你要自己指定初始capacity的话,不要搞得太大,那样不仅浪费空间,而且浪费时间。LinkedHashSet的遍历时间只与元素个数成正比
Set有两种special-purpose的实现类:EnumSet和CopyOnWriteArraySet。
·EnumSet的空间和时间性能都很好,可以作为传统上基于int的“位标志”的替换形式,具有高品质、类型安全的优势。
·CopyOnWriteArraySet适合于遍历操作的数量大大超过可变操作的数量时,以及在不能或不想进行同步遍历,但又需要从并发线程中排除冲突时很有用
具体请参见API doc
2. List实现类
List有两种General-purpose的实现类:ArrayList和LinkedList。一般情况下,使用ArrayList总是最好的选择,因为他占用空间小,速度又快。除非你需要大量频繁的插入删除操作,这时LinkedList可能更加适合。
ArrayList能在构造函数中指定capacity,LinkedList不能。
List有一种special-purpose的implementation - CopyOnWriteArrayList,具体参考API doc
3. Queue实现类
Queue有两种general-purpose的实现类:LinkedList和PriorityQueue。LinkedList提供了一种FIFO队列,而PriorityQueue则是根据元素的自然顺序或是指定的Comparator来排列元素。
在java.util.concurrent包里又一个扩展了Queue的BlockingQueue接口。他有如下一些实现类:
4. Map实现类
Map有三种general-purpose的实现类:HashMap、TreeMap和LinkedHashMap。如果你需要SortedMap的操作,或者需要按序遍历Map,就用TreeMap;如果你不关心遍历的顺序,只关心速度,那就用HashMap;如果你需要接近于HashMap的性能,又想能按元素插入顺序来遍历,就用LinkedHashMap。
其实Map和Set是很相似的,只不过一个是元素集合,一个是“键值对”集合。上面介绍的Set中各实现类的性质也同样适用于Map
需要注意的是,LinkedHashMap提供了一个方法:
removeEldestEntry。通过重写这个方法,可以定义自觉的策略-
在将新映射关系添加到映射时自动移除旧的映射关系。具体参见API doc
Map有三种Special-purpose的实现类:EnumMap, WeakHashMap,和IdentityHashMap。
Map的Concurrent实现类:ConcurrentHashMap。
下面来介绍一下Wrapper实现类
Wrapper实现类是在提供的Collection实例基础之上添加一些额外的功能,就好像设计模式中的
decorator
所有的Wrapper都包含在Collections类中,有static方法来创建。
1. Synchronization Wrappers
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);
需要注意的是,不要以为加上Synchronization Wrappers的包装就可以不管同步操作了,当遍历的时候,我们还是要对Collection对象加上对象
加上对象锁。这是因为遍历操作是由对Collection内部的多个操作的调用组成的。
下面的代码演示了如何在遍历时同步:
Collection<Type> c =
Collections.synchronizedCollection(myCollection);
synchronized(c) {
for (Type e : c)
foo(e);
}
注意如果我们是在遍历Map,不管我们是用key还是用value什么遍历,都要将锁加在Map上:
Map<KeyType, ValType> m =
Collections.synchronizedMap(new HashMap<KeyType, ValType>());
Set<KeyType> s = m.keySet();
synchronized(m) { // Synchronizing on m, not s!
while (KeyType k : s)
foo(k);
}
2. Unmodifiable Wrappers
Unmodifiable Wrappers提供如下两种用途:
2.1. 使Collection不可修改。注意要做到这一点,我们必须在使用Unmodifiable Wrappers后,放弃原来的Collection的引用。
2.2. 运行某客户端对你的数据进行只读操作。这时你可以保留原本的Collection的引用,使得你可以随意操作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);
3. Checked Interface Wrappers
Collections类中提供的各种Collections.checked... 操作,返回指定 collection 的一个动态类型安全视图。试图插入一个错误类型的元素将
导致立即抛出 ClassCastException。假设在生成动态类型安全视图之前,collection 不包含任何类型不正确的元素,并且所有对该collection
的后续访问都通过该视图进行,则可以保证 该 collection 不包含类型不正确的元素。
具体参见API doc
4. Convenience Implementations
4.1 List View of an Array - Arrays.asList()
Arrays.asList()方法返回数组的一个List视图。任何对返回的list上的操作都将写回到数组上,反之亦然。但要注意的是,返回的list并不支持
add、remove操作。
Q:如何得到一个固定长度的list?
A:List<String> list = Arrays.asList(new String[size]);
4.2 Immutable Multiple-Copy List
参见Collections.nCopies()方法
4.3 Immutable Singleton Set
参见Collections.singleton()方法
4.4 Empty Set, List, and Map Constants
Collections.emptySet(), Collections.emptyList(), Collections.emptyMap()