Queue
Queue队列是Collection类的子类,是一种特殊集合,存储方式为先进先出,后进后出原则。
从其存储方式可以判断, Queue 队列是有序存储的,其与 List 集合的差异为:
List: 可以在任意位置进行存储、获取和删除元素;Queue: 只能在集合尾部插入元素,且只能在头部获取/删除元素。
常用方法
//新增
boolean add(E e);
boolean offer(E e);
//获取并删除
E remove();
E poll();
//获取不删除
E element();
E peek();Queue 队列提供了两套常用的增、删、查方案。区别为当队列内容异常时是否通过异常提醒。
抛异常的方法
add
在尾部插入元素。
Queue 队列有最大容量限制。当插入元素时没有超出最大容量,则返回true;否则,会抛出异常:IllegalStateException。
remove
在头部获取元素并删除。
当队列为空时,抛出异常 NoSuchElementException。
element
获取队列头部元素且不删除。
当队列为空时,抛出异常 NoSuchElementException。
不抛异常的方法
offer
在尾部插入元素。
如果元素已添加到此队列,则为 true ,否则为 false。
poll
在头部获取元素并删除。
当队列为空时,则返回 null 。
peek
获取队列头部元素且不删除。
如果此队列为空,则返回 null 。
代码演示
Queue<String> queue = new LinkedList<>();
// 入队
queue.add("1");
queue.add("2");
queue.offer("3");
System.out.println(queue);
// 出队
System.out.println(queue.poll());
System.out.println(queue);
System.out.println(queue.remove());
System.out.println(queue);
queue.offer("4");
System.out.println(queue.peek());
System.out.println(queue.element());
System.out.println(queue);注意
队列进行插入操作时,应尽量避免插入 null 元素,否则进行获取操作时,无法判断是队列为空还是元素为 null 导致。
PriorityQueue
优先级队列,与
Queue队列不同的是,在进行获取元素时,会根据优先级的不同自动获取优先级最高的元素优先获取。
案例:
在银行办理业务,根据取票号排序为 A1,A2,A3…A20,正常办理的话可以根据队列 Queue 实现。但如果有vip用户办理需要插队操作,比如此时A5刚办理结束,下一个应该叫号为VIP1而不是A6。
实现
public static void main(String[] args) {
Queue<String> queue = new PriorityQueue<>();
queue.add("A1");
queue.add("A2");
queue.add("A3");
queue.add("v1");
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());
}直接使用队列,没有设定优先级无法实现需求。
在初始化 PriorityQueue 队列时,需要定义比较规则,才能进行优先级排序。
public PriorityQueue(Comparator<? super E> comparator) {
this(DEFAULT_INITIAL_CAPACITY, comparator);
}改进:
PriorityQueue<UserDemo> userDemos = new PriorityQueue<>(new UserComparator());
userDemos.add(new UserDemo("张三",10));
userDemos.add(new UserDemo("李四",11));
userDemos.add(new UserDemo("王五",9));
System.out.println(Objects.requireNonNull(userDemos.poll()).getName());
System.out.println(Objects.requireNonNull(userDemos.poll()).getName());
System.out.println(Objects.requireNonNull(userDemos.poll()).getName());
public class UserComparator implements Comparator<UserDemo> {
@Override
public int compare(UserDemo o1, UserDemo o2) {
return o1.getAge() - o2.getAge();
}
}Deque
Queue队列为先入先出队列,限制较大。而Deque队列可以在队头和队尾都可以进行添加和回去操作,称为双端队列。
特点
- 可在队头和队尾进行添加和删除操作。
常用方法
| 描述 | 方法 |
|---|---|
| 队头新增 | offerFirst/addFirst |
| 队头获取不删除 | getFirst/peekFirst |
| 队头获取并删除 | removeFirst/pollFirst |
| 队尾新增 | addLast/offerLast |
| 队尾获取不删除 | getLast/peekLast |
| 队尾获取并删除 | removeLast/pollLast |
代码演示
public static void main(String[] args) {
Deque<String> deque = new LinkedList<>();
deque.offerFirst("1");
deque.addFirst("2");
System.out.println(deque.pollFirst());
System.out.println(deque.getFirst());
System.out.println(deque.peekFirst());
System.out.println(deque.removeFirst());
deque.offerLast("3");
deque.addLast("4");
System.out.println(deque.pollLast());
System.out.println(deque.getLast());
System.out.println(deque.peekLast());
System.out.println(deque.removeLast());
}说明
Deque继承于Queue,可以通用队列的offer、peek、poll等方法,但推荐使用自己的专属方法;LinkedList即实现了Deque又实现了Queue使用时需根据不用的需要定义不同的接口。Deque<String> deque = new LinkedList<>();