先来看看集合Collection的继承关系图:
Collection接口主要分为三类:List、Set、Queue。
List:有序、有下标、可重复
Set:无序(LinkedHashSet除外)、无下标、无重复
Queue:队列
ArrayList用的比较多,可以做个详细的讲解。
LinkedList实现了List接口和Deque接口,底层采用链表实现,下标查询和插入比较慢,优点是作为队列。
Vector和Stack是同步容器,单线程用的话比较慢,底层是数组实现的。
HashSet底层采用的是HashMap来实现的。value是一个final Object,因为移除的时候可以判断是否移除成功。
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
LinkedHashSet底层采用的LinkedHashMap来实现的。
TreeSet底层采用的是TreeMap来实现。
其实List和Set都比较简单。下面来看看Queue。Queue下面有双端队列Deque、阻塞队列BlockingQueue。
- add 增加一个元索 如果队列已满,则抛出一个IIIegaISlabEepeplian异常
- remove 移除并返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
- element 返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
- offer 添加一个元素并返回true 如果队列已满,则返回false
- poll 移除并返问队列头部的元素 如果队列为空,则返回null
- peek 返回队列头部的元素 如果队列为空,则返回null
- put 添加一个元素 如果队列满,则阻塞
- take 移除并返回队列头部的元素 如果队列为空,则阻塞
下面的表格很明显:
4.1 ArrayBlockingQueue
ArrayBlockingQueue是一个有边界的阻塞队列,它的内部实现是一个数组。有边界的意思是它的容量是有限的,我们必须在其初始化的时候指定它的容量大小,容量大小一旦指定就不可改变。
ArrayBlockingQueue是以先进先出的方式存储数据,最新插入的对象是尾部,最新移出的对象是头部。
4.2 LinkedBlockingQueue
LinkedBlockingQueue阻塞队列大小的配置是可选的,如果我们初始化时指定一个大小,它就是有边界的,如果不指定,它就是无边界的。说是无边界,其实是采用了默认大小为Integer.MAX_VALUE的容量 。它的内部实现是一个链表。
和ArrayBlockingQueue一样,LinkedBlockingQueue 也是以先进先出的方式存储数据,最新插入的对象是尾部,最新移出的对象是头部。
4.3 PriorityBlockingQueue
PriorityBlockingQueue是一个没有边界的队列,它的排序规则和 java.util.PriorityQueue一样。需要注意,PriorityBlockingQueue中允许插入null对象。
所有插入PriorityBlockingQueue的对象必须实现 java.lang.Comparable接口,队列优先级的排序规则就是按照我们对这个接口的实现来定义的。
4.4 SynchronousQueue
SynchronousQueue队列内部仅允许容纳一个元素。当一个线程插入一个元素后会被阻塞,除非这个元素被另一个线程消费。
4.5 DelayQueue
getDelay()方法的返回值就是队列元素被释放前的保持时间,如果返回0或者一个负值,就意味着该元素已经到期需要被释放,此时DelayedQueue会通过其take()方法释放此对象。
一、ArrayList详解
- 默认数组长度10,每次扩容size的一半 int newCapacity = oldCapacity + (oldCapacity >> 1)
- 当元素满了的时候,再添加新元素就会触发扩容
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//扩容后的大小
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
//复制之前的元素
elementData = Arrays.copyOf(elementData, newCapacity);
}
- 用迭代器遍历的时候,如果并发修改容器的元素,就会抛异常。这个也叫做快速失败。
final void checkForComodification() {
//modCount ArrayList的成员变量,每次修改的时候,都会+1
//expectedModCount 创建迭代器的时候,modCount的值
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}