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<>();