Collection集合框架图
首先我们先来看看Collection集合框架全家福,然后再逐一攻破。
Iterable
Collection集合框架顶层接口,定义了返回迭代器的方法,使得所有子类都能够支持for each循环。
Iterator
iterator为Java中的迭代器对象,是能够对List这样的集合进行迭代遍历的底层依赖,只能朝后遍历对象。通过Iterator进行遍历修改、删除集合类元素是唯一安全的方式,下面是该类的方法:
| 方法名 | 方法描述 |
|---|---|
| boolean hasNext() | 如果迭代器中还有元素,则返回true |
| E next() | 返回迭代器中的下一个元素 |
| void remove() | 删除迭代器新返回的元素 |
| void forEachRemaining(Consumer<? super E> action) | 为每个剩余元素执行给定的操作,直到所有的元素都已经被处理或行动将抛出一个异常 |
ListIterator
ListIterator继承于Iterator接口,只能用于各种List类型的访问。它比Iterator的功能更强大,相比于Iterator增加了以下功能:
(1)双向移动(向前/向后遍历)。
(2)可以使用nextIndex()和previousIndex()获取下一个元素所在的索引。
(3)可以使用set()方法修改元素。
(4)可以使用add()方法添加元素。
Collection
Collection继承了Iterable接口,是List,Set,Queue等接口的父类。下面是一些常用方法:
| 方法名称 | 方法描述 |
|---|---|
| boolean add(Object obj) | 添加一个元素 |
| boolean addAll(Collection c) | 添加一个集合的全部元素 |
| void clear() | 移除所有元素 |
| boolean remove(Object o) | 移除一个元素 |
| boolean removeAll(Collection c) | 移除此 collection 中那些也包含在指定 collection 中的所有元素 |
| boolean contains(Object o) | 如果此 collection 包含指定的元素,则返回 true |
| boolean containsAll(Collection c) | 如果此 collection 包含指定 collection 中的所有元素,则返回 true |
| boolean isEmpty() | 判断集合是否为空 |
| int size() | 获取元素的个数 |
| boolean retainAll(Collection c) | 仅保留此 collection 中那些也包含在指定 collection 的元素 |
| Object[] toArray() | 返回包含此 collection 中所有元素的数组 |
| T[] toArray(T[] a) | 返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同 |
List
List继承了Collection接口,拥有Collection集合的所有方法。常见的子类有ArrayList,LinkedList,Vector,CopyOnWriteArrayList等。
List是一个有序可重复的集合。
ArrayList
ArrayList是Java集合框架中使用最多的一个类,是一个数组队列,线程不安全集合。它继承于AbstractList,实现了List,RandomAccess,Cloneable,Serializable接口。它有如下特点:
- 容量不固定,随着容量的增加而动态扩容(阈值基本不会达到)
- 有序集合(插入的顺序==输出的顺序)
- 插入的元素可以为null
- 查改效率更高(相对于LinkedList来说)
- 线程不安全
LinkedList
LinkedList是一个继承于AbstractSequentialList的双向链表,实现了List,Deque,Cloneable,Serializable接口。他有如下特点:
- 允许null值
- 内部以双向链表的形式来保存集合中的元素
- 可以当做双端队列、栈来使用
- 元素是有序的,输出顺序与输入顺序一致
- 所有指定位置的操作都是从头开始遍历进行的
- 增删效率更高(相对于ArrayList来说)
- 线程不安全
Vector
Vector 是矢量队列,它是JDK1.0版本添加的类。继承于AbstractList,实现了List,RandomAccess,Cloneable,Serializable接口。与ArrayList数据结构相似,不同的是Vector是线程安全的。
CopyOnWriteArrayList
CopyOnWrite即写入时复制,用于替代同步List,在每次写数据时都会创建一个新的副本,并且内部使用了ReentrantLock进行同步控制,因此是线程安全的。它实现了List,RandomAccess,Cloneable,Serializable接口。特点如下:
- 线程安全
- 适用于读多写少
- 耗内存
- 不能保证数据的实时一致性
Set
Set继承了Collection接口,拥有Collection集合的所有方法。常见的子类有HashSet,TreeSet,LinkedHashSet等。
Set是一个不可重复集合。
HashSet
HashSet是一个无序集合,实际上是一个HashMap实例,允许为null。
HashSet继承了AbstractSet,实现了Set,Cloneable,Serializable接口。
TreeSet
TreeSet常用来给对象排序,因为它构造时可以传入比较器Comparator,在添加元素的时候会根据比较器Comparator的规则进行排序。若没有传比较器Comparator,则会调用对象默认的比较方法compareTo(),该对象需实现Comparable接口,否则报错。
TreeSet继承了AbstractSet,实现了NavigableSet,Cloneable,Serializable接口。
LinkedHashSet
LinkedHashSet值得关注的点是它是一个有序的不可重复的集合。
LinkedHashSet继承了HashSet,实现了Set,Cloneable,Serializable接口。
Queue
Queue是一种队列的数据结构,支持FIFO(先进先出),尾部添加、头部删除。它继承了Collection接口,除了拥有所有的Collection内的方法,Queue还实现了自己的一些方法:
| 方法名称 | 方法描述 |
|---|---|
| boolean add(E e) | 添加一个元素并返回true,如果队列已满,则抛出一个IIIegaISlabEepeplian异常 |
| boolean offer(E e) | 添加一个元素并返回true,如果队列已满,则返回false |
| E remove() | 移除并返回队列头部的元素,如果队列为空,则抛出一个NoSuchElementException异常 |
| E poll() | 移除并返问队列头部的元素,如果队列为空,则返回null |
| E element() | 返回队列头部的元素,如果队列为空,则抛出一个NoSuchElementException异常 |
| E peek() | 返回队列头部的元素,如果队列为空,则返回null |
Deque
Deque为双端队列,继承了Queue接口。Deque既支持FIFO(先进先出)又支持LIFO(后进先出)。它实现了一些队列的操作方法:
| 方法名称 | 方法描述 |
|---|---|
| void push(E) | 向队列头部插入一个元素,失败时抛出异常 |
| void addFirst(E) | 向队列头部插入一个元素,失败时抛出异常 |
| void addLast(E) | 向队列尾部插入一个元素,失败时抛出异常 |
| boolean offerFirst(E) | 向队列头部加入一个元素,失败时返回false |
| boolean offerLast(E) | 向队列尾部加入一个元素,失败时返回false |
| E getFirst() | 获取队列头部元素,队列为空时抛出异常 |
| E getLast() | 获取队列尾部元素,队列为空时抛出异常 |
| E peekFirst() | 获取队列头部元素,队列为空时返回null |
| E peekLast() | 获取队列尾部元素,队列为空时返回null |
| boolean removeFirstOccurrence(Object) | 删除第一次出现的指定元素,不存在时返回false |
| boolean removeLastOccurrence(Object) | 删除最后一次出现的指定元素,不存在时返回false |
| E pop() | 取出队列头部元素,队列为空时抛出异常 |
| E removeFirst() | 取出队列头部元素,队列为空时抛出异常 |
| E removeLast() | 取出队列尾部元素,队列为空时抛出异常 |
| E pollFirst() | 取出队列头部元素,队列为空时返回null |
| E pollLast() | 取出队列尾部元素,队列为空时返回null |
| Iterator descendingIterator() | 返回队列反向迭代器 |
ArrayDeque
ArrayDeque是一个大小可变的数组双端队列,不允许插入null。
ArrayDeque继承了AbstractCollection抽象类,实现了Deque接口。
ConcurrentLikedDeque
ConcurrentLikedDeque是一个大小可变且线程安全的链表双端队列,非阻塞,不允许插入null。
ConcurrentLikedDeque继承了AbstractCollection抽象类,实现了Deque接口。
BlockingDeque
BlockingDeque是一个阻塞双端队列,线程可以安全的插入和取出元素。线程插入或者移出队列中的元素时,可能会阻塞。
BlockingDeque继承了Deque和BlockingQueue接口。
LinkedBlockingDeque
LinkedBlockingDeque是基于双向链表的双端有界阻塞队列,默认使用非公平ReentrantLock实现线程安全,不允许null元素添加。
LinkedBlockingDeque继承了AbstractQueue抽象类,实现了BlockingDeque接口。
AbstractQueue
AbstractQueue是一个抽象类,继承了AbstractCollection抽象类,同时实现了Queue接口。提供了一些队列方法操作的方法实现。
PriorityQueue
PriorityQueue即优先队列,优先队列的作用是能保证每次取出的元素都是队列中权值最小的(Java的优先队列每次取最小元素,C++的优先队列每次取最大元素)。这里牵涉到了大小关系,元素大小的评判可以通过元素本身的自然顺序(natural ordering),也可以通过构造时传入的比较器(Comparator,类似于C++的仿函数)。
ConcurrentLinkedQueue
ConcurrentLinkedQueue一个基于链接节点的,无界的,线程安全的FIFO队列。当许多线程共享访问一个公共Collection时,ConcurrentLinkedQueue是一个恰当的选择。
BlockingQueue
BlockingQueue是一个阻塞队列接口,实现了对队列阻塞功能。他继承了Queue接口。在队列的基础上增加了几个阻塞方法:
| 方法名称 | 方法描述 |
|---|---|
| void put(E e) | 将元素插入此队列的尾部,如果该队列已满,则一直阻塞 |
| void take(E e) | 取出队列头部元素,若队列没有元素,则一直阻塞。 |
| boolean offer(E e, long timeout, TimeUnit unit) | 将元素插入此队列的尾部,可以设置超时时间 |
| E poll(long timeout, TimeUnit unit) | 取出队列头部元素,可以设置超时时间 |
ArrayBlockingQueue
ArrayBlockingQueue是一个由数组结构组成的有界阻塞队列,遵循FIFO原则。
LinkedBlockingQueue
LinkedBlockingQueue是一个由链表结构组成的有界阻塞队列,遵循FIFO原则,默认和最大长度为Integer.MAX_VALUE。
PriorityBlockingQueue
PriorityBlockingQueue是一个支持优先级排序的无界阻塞队列。
DelayQueue
DelayQueue是一个使用优先级队列实现的无界阻塞队列。
SynchronousQueue
SynchronousQueue一个不存储元素的阻塞队列。
TransferQueue
TransferQueue(java7引入)继承了BlockingQueue并扩展了一些新方法。生产者会一直阻塞直到所添加到队列的元素被某一个消费者所消费。
当我们不想生产者过度生产消息时,TransferQueue可能非常有用,可避免发生OutOfMemory错误。
LinkedTransferQueue
LinkedTransferQueue实现了TransferQueue接口,是一个由链表结构组成的无界阻塞队列。
LinkedTransferQueue实际上是ConcurrentLinkedQueue、SynchronousQueue(公平模式)和LinkedBlockingQueue的超集。