Java集合是面试中经常被问到的一块内容,很多人在这个地方被面试官吊打。Java集合类被定义在java.util包中,主要有四种集合,分别是List、Queue、Set和Map,每种集合分类如下图所示
List集合
List是一种在开发中比较常用的集合类,作为有序的Collection的典范,分别有如下的三个实现类
- ArrayList
- Vector
- LinkedList
从名字可以看出三个实现类分别都代表什么。
ArrayList
ArrayList底层是通过数组实现的,既然是数组那么它就有数组带给它的属性,增加和删除速度慢,但是查询速度快,是线程不安全的。
ArrayList的缺点是元素必须是连续的存储,当需要在ArrayList中间插入一个或者删除一个元素的时候,需要将待插入或者删除节点之后的所有的元素进行移动。所以ArrayList不适合随机插入和删除操作。适合的操作是遍历和随机查找。可以通过下标直接找到对应的元素。
ArrayList 不需要在定义的时候指定数组的长度,而是在数据存储长度不足的时候,ArrayList会创建一个新的更大的数组并且将数组中已经有的数据复制到新的数组中。
Vector
Vector基于数组实现,增加和删除速度慢,查询速度快,是线程安全的。
Vector的数据结构与ArrayList的结构是一样的,都是基于数组的方式进行实现的。与ArrayList不同的是Vector支持线程同步操作,也就是说同一时刻只允许一个线程对Vector进行写操作,这样保证了在多线程的环境下的数据一致性问题,但是需要对Vector进行反复的加锁释放锁的操作,所以Vector在读写操作上的速度的要比ArrayList低。
LinkedList
LinkedList是基于双向链表,增加和删除的速度快,查询的速度慢,是线程不安全的。
LinkedList采用的双向链表的数据结构进行存储元素,在对LinkedList进行插入和删除操作的时候,只需要在对应的节点上插入或者删除对应的元素即可,并且将节点的指针进行修改就可以了,数据变动是最小的,这样做的话插入和删除的效率很高。由于是链表数据结构,在随机访问的时候,需要从链表的头部一直遍历到对应的节点才能找到对应的元素,所以随机访问的速度较慢。除此之外,LinkedList 还提供了在List接口中未定义的方法,用来操作链表头部和尾部的元素,所以有的时候也可以当做堆栈、队列或者双向队列来使用。
Queue
队列也是一种特殊的线性表,它只允许在两端进行操作,插入或者取出,不允许操作中间的数据。比如只允许在对头出队,队尾入队。这样就具有先进先出的特性(first in first out-FIFO)。就像排队买东西一样,不允许插队,先排先买。
队列分为单向队列(有序队列),就是上面所说的排队模型,先进先出的操作,只允许一边进,另一边出,比如Java中的Queue。另外一种就是双端队列,两端都可以进行进出操作。比如java中的Deque。
Queue是队列结构,在Java中常见的几种队列结构如下
- ArrayBlockingQueue:基于数组数据结构实现的有界阻塞队列形式
- LinkedBlockingQueue:基于链表数据结构实现的有界阻塞队列
- PriorityBlockingQueue:支持优先级排序的无界阻塞式队列形式
- DelayQueue:支持延迟操作的无界阻塞队列
- SynchronousQueue:用于线程同步的阻塞队列
- LinkedTransferQueue:基于链表实现的无界阻塞队列
- LinkedBlockingDeque:基于链表实现的双向阻塞队列
代码如下所示
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 有界队列的基本实现
*/
public class MyQueue {
private LinkedList<Object> list = new LinkedList<>();
private AtomicInteger count = new AtomicInteger(0);
private final int minSize = 0;
private int maxSize;
private final Objec