Java Queue 佇列

Queue 是先進先出(FIFO)的資料結構介面,元素從尾端加入,從頭端取出。

引入套件

import java.util.Queue;
import java.util.LinkedList;
import java.util.ArrayDeque;
import java.util.PriorityQueue;

建立 Queue

// 使用 LinkedList
Queue<String> queue1 = new LinkedList<>();

// 使用 ArrayDeque(推薦)
Queue<String> queue2 = new ArrayDeque<>();

// 優先佇列
Queue<Integer> pq = new PriorityQueue<>();

基本操作

Queue<String> queue = new LinkedList<>();

// 入列
queue.add("A");      // 失敗時拋例外
queue.offer("B");    // 失敗時回傳 false

// 查看頭端(不移除)
String head1 = queue.element();  // 空時拋例外
String head2 = queue.peek();     // 空時回傳 null

// 出列
String item1 = queue.remove();   // 空時拋例外
String item2 = queue.poll();     // 空時回傳 null

// 其他
int size = queue.size();
boolean empty = queue.isEmpty();

方法比較

操作拋例外回傳特殊值
入列add(e)offer(e)
出列remove()poll()
查看element()peek()

Deque 雙端佇列

Deque<String> deque = new ArrayDeque<>();

// 頭端操作
deque.addFirst("A");
deque.offerFirst("B");
String first = deque.removeFirst();
String peekFirst = deque.peekFirst();

// 尾端操作
deque.addLast("C");
deque.offerLast("D");
String last = deque.removeLast();
String peekLast = deque.peekLast();

PriorityQueue 優先佇列

// 最小堆(預設)
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
minHeap.addAll(Arrays.asList(5, 1, 3, 2, 4));

while (!minHeap.isEmpty()) {
    System.out.print(minHeap.poll() + " ");  // 1 2 3 4 5
}

// 最大堆
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Comparator.reverseOrder());
maxHeap.addAll(Arrays.asList(5, 1, 3, 2, 4));

while (!maxHeap.isEmpty()) {
    System.out.print(maxHeap.poll() + " ");  // 5 4 3 2 1
}

自訂排序

record Task(String name, int priority) {}

PriorityQueue<Task> tasks = new PriorityQueue<>(
    Comparator.comparingInt(Task::priority)
);

tasks.add(new Task("Low", 3));
tasks.add(new Task("High", 1));
tasks.add(new Task("Medium", 2));

while (!tasks.isEmpty()) {
    System.out.println(tasks.poll().name());
}
// High
// Medium
// Low

實用範例

BFS 廣度優先搜尋

public static void bfs(Map<Integer, List<Integer>> graph, int start) {
    Queue<Integer> queue = new LinkedList<>();
    Set<Integer> visited = new HashSet<>();
    
    queue.offer(start);
    visited.add(start);
    
    while (!queue.isEmpty()) {
        int node = queue.poll();
        System.out.print(node + " ");
        
        for (int neighbor : graph.getOrDefault(node, List.of())) {
            if (!visited.contains(neighbor)) {
                visited.add(neighbor);
                queue.offer(neighbor);
            }
        }
    }
}

任務排程

Queue<Runnable> taskQueue = new LinkedList<>();

taskQueue.offer(() -> System.out.println("Task 1"));
taskQueue.offer(() -> System.out.println("Task 2"));
taskQueue.offer(() -> System.out.println("Task 3"));

while (!taskQueue.isEmpty()) {
    taskQueue.poll().run();
}

重點整理

  • Queue 是 FIFO(先進先出)資料結構
  • 優先使用 ArrayDeque 而非 LinkedList
  • offer/poll/peek 較安全,失敗不拋例外
  • Deque 支援雙端操作
  • PriorityQueue 依優先順序出列
  • 常用於 BFS、任務排程等場景