Java 中的 Collection

Java 中的集合包括三大类,分别是 Set(集)、List(列表)、Map(映射),它们都位于 java.util 包下,Set、List 和 Map 都是接口,各有各自的实现类。Set 的常用实现类有 TreeSet 和 HashSet,List 的常用实现类有 ArrayList 和 LinkedList,Map 的常用实现类有 HashMap 和 TreeMap 等。

Collection

Collection 是最基本的集合接口,声明了适用于 Java 集合的通用方法,Set 和 List 都继承自 Collection 接口。

1
2
3
4
5
6
7
---|Collection<E>
---|Set<E>
---|TreeSet<E>
---|HashSet<E>
---|List<E>
---|ArrayList<E>
---|LinkedList<E>

下面是 Collection 接口中一些常用的 API:

Return Type Method Description
boolean add(E e) 确保集合中包含指定的元素
boolean addAll(Collection<? extends E> c) 将指定集合中的所有元素添加到此集合中
void clear() 从此集合中删除所有元素
boolean contains(Object o) 如果此集合中包含指定的元素则返回 true
boolean containsAll(Collection<?> c) 如果此集合包含指定集合中的所有元素则返回 true
boolean isEmpty() 如果此集合不包含元素则返回 true
Iterator iterator() 返回此集合中的元素的迭代器
boolean remove(Object o) 从此集合中删除指定元素
boolean removeAll(Collection<?> c) 从此集合中删除指定集合包含的所有元素
int size() 返回此集合中的元素数量
Object[] toArray() 返回一个包含此集合中所有元素的数组

Set

Set 具有与 Collection 完全一样的接口,因此没有任何额外的功能。实际上 Set 就是 Collection,只是行为不同。

Set: 存入 Set 的每个元素都必须是唯一的,因为 Set 不保存重复元素。加入 Set 的元素必须重写 equals() 方法以确保对象的唯一性。Set 接口不保证维护元素的次序。

TreeSet: 保存次序的 Set,底层为树结构。使用它可以从Set中提取有序的序列。

HashSet: 为快速查找设计的 Set。存入 HashSet 的对象必须重写 hashCode() 方法。

List

List: 次序是 List 最大的特点,它保证元素可以按照特定的顺序排列。下面是 List 新增的一些常用 API:

Return Type Method Description
boolean add(E e) 将指定元素添加到此列表的末尾
void add(int index, E element) 将指定元素添加到此列表中的指定位置
E get(int index) 返回此列表中指定位置的元素
int indexOf(Object o) 返回此列表中指定元素第一次出现的索引,如果此列表不包含该元素则返回 -1
int lastIndexOf(Object o) 返回此列表中指定元素最后一次出现的索引,如果此列表不包含该元素则返回 -1
E remove(int index) 从此列表中删除指定位置的元素
boolean remove(Object o) 从此列表中删除第一次出现的指定元素
E set(int index, E element) 用指定的元素替换此列表中指定位置的元素
void sort(Comparator<? super E> c) 使用 Comparator 比较器将此列表中的元素重新排序

ArrayList: 由数组实现的 List,实现了随机访问的接口,允许对元素进行快速随机访问,但是向 List 中间插入与移除元素的速度比较慢。

LinkedList: 基于链表实现的 List,对顺序访问进行了优化,向 List 中间插入与删除的开销并不大,但随机访问则相对较慢。除了上面的方法以外 LinkedList 还有下列常用 API:

Return Type Method Description
boolean add(E e)/offer(E e) 将指定元素添加到此列表的末尾
void/boolean/void addFirst(E e)/offerFirst(E e)/push(E e) 在此列表开头插入指定的元素
void/boolean addLast(E e)/offerLast(E e) 将指定的元素追加到此列表的末尾
E getFirst() 返回此列表中的第一个元素
E getLast() 返回此列表中的最后一个元素
E removeFirst()/pop() 删除并返回此列表中第一个元素
E removeLast() 删除并返回此列表中最后一个元素

如果对于 LinkedList 中多个方法都是同一个功能感到疑惑,看一下 LinkedList 的源码你就懂了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package java.util;

public class LinkedList<E> extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable {

// 省略其它代码

public boolean offer(E e) {
return add(e);
}

public boolean offerFirst(E e) {
addFirst(e);
return true;
}

public boolean offerLast(E e) {
addLast(e);
return true;
}

public void push(E e) {
addFirst(e);
}

public E pop() {
return removeFirst();
}
}

小结

集合 使用场景 线程安全 可否添加 null
Set 不需要保留存储顺序,并且需要去掉重复元素
TreeSet 需要将元素排序 × ×
HashSet 不需要将元素排序 ×
List 需要保留存储顺序,并且保留重复元素
ArrayList 查询多,增删少 ×
LinkedList 增删多,查询少 ×

Map

Map 是一种使用「键值对」的方式来存储数据的集合,每个「键」映射一个「值」,可以通过「键」来获取对应的「值」。下面是 Map 接口中常用的一些 API:

Return Type Method Description
void clear() 删除该 Map 中所有的映射
boolean containsKey(Object key) 如果此 Map 包含指定键的映射,则返回 true
boolean containsValue(Object value) 如果此 Map 将一个或多个键映射到指定的值,则返回 true
V get(Object key) 返回此 Map 指定键对应的值,如果不存在返回 null
Set keySet() 返回此 Map 中包含的键的 Set 集合
V put(K key, V value) 将指定的值与指定键相关联
V remove(Object key) 从此 Map 中删除指定键的映射
int size() 返回此 Map 中键值映射的数量
Collection values() 返回此 Map 中包含的值的 Collection 集合

HashMap: 基于散列表的实现。插入和查询「键值对」的开销是固定的。

TreeMap: 基于红黑树数据结构的实现。查看「键」或「键值对」时,它们会被排序(次序由 Comparabel 或 Comparator 决定)。TreeMap 的特点在于,得到的结果是经过排序的。TreeMap 是唯一的带有 subMap() 方法的 Map,它可以返回一个子树。

Hashtable: 和 HashMap 一样也是一个散列表,不过它的函数都是同步的,这意味着它是线程安全的。它的 key、value 都不可以为 null。此外,Hashtable 中的映射不是有序的。

小结

Map 使用场景 线程安全 键可否为 null 值可否为 null
HashMap 适用于 Map 中插入、删除和定位元素 ×
TreeMap 适用于按自然顺序或自定义顺序遍历键(key) × ×
Hashtable 适用于多线程时保证线程安全 × ×

参考资料