杰瑞科技汇

Java中Queue与List如何选择?

Of course! Here is a comprehensive guide to using queues in Java, covering the core concepts, different implementations, and common operations.

Java中Queue与List如何选择?-图1
(图片来源网络,侵删)

What is a Queue?

In computer science, a Queue is a fundamental data structure that follows the First-In, First-Out (FIFO) principle. Think of a real-world queue or a line at a supermarket checkout: the first person to join the line is the first person to be served.

Key Characteristics:

  • FIFO (First-In, First-Out): The first element added to the queue will be the first one to be removed.
  • Two Main Operations:
    • Enqueue: Add an element to the back (or tail) of the queue.
    • Dequeue: Remove an element from the front (or head) of the queue.

The Queue Interface in Java

Java provides a Queue interface in the java.util package. It's important to remember that Queue is an interface, not a concrete class. This means you cannot instantiate it directly. You must use one of its concrete implementations.

Common Methods in the Queue Interface:

Java中Queue与List如何选择?-图2
(图片来源网络,侵删)
Method Description Throws Exception? Returns Special Value?
add(e) Inserts the specified element into the queue. IllegalStateException (if full) -
offer(e) Inserts the specified element into the queue. No true (if successful), false (if full)
remove() Retrieves and removes the head of the queue. NoSuchElementException (if empty) -
poll() Retrieves and removes the head of the queue. No null (if empty)
element() Retrieves, but does not remove, the head of the queue. NoSuchElementException (if empty) -
peek() Retrieves, but does not remove, the head of the queue. No null (if empty)

Key Takeaway: The add()/remove()/element() methods throw exceptions if they fail, while the offer()/poll()/peek() methods return a special value (null or false). It's often safer to use the latter to avoid unexpected program crashes.


Common Queue Implementations in Java

Here are the most popular implementations you will use.

LinkedList

A LinkedList class implements the Queue interface. It's a good general-purpose choice because it's resizable and doesn't have a fixed capacity.

Characteristics:

Java中Queue与List如何选择?-图3
(图片来源网络,侵删)
  • Unbounded: Can grow as needed.
  • Doubly-linked list: Good for adding/removing from both ends.
  • Order: Maintains insertion order (FIFO).
import java.util.LinkedList;
import java.util.Queue;
public class LinkedListQueueExample {
    public static void main(String[] args) {
        // Create a Queue using LinkedList
        Queue<String> queue = new LinkedList<>();
        // --- Adding Elements (Enqueue) ---
        // add() will throw an exception if the queue were bounded and full
        queue.add("Alice");
        queue.add("Bob");
        queue.add("Charlie");
        System.out.println("Initial Queue: " + queue); // [Alice, Bob, Charlie]
        // offer() is preferred as it returns false if it can't add
        queue.offer("David");
        System.out.println("Queue after offer: " + queue); // [Alice, Bob, Charlie, David]
        // --- Removing Elements (Dequeue) ---
        // remove() will throw an exception if the queue is empty
        String removedPerson = queue.remove();
        System.out.println("Removed by remove(): " + removedPerson); // Alice
        System.out.println("Queue after remove(): " + queue); // [Bob, Charlie, David]
        // poll() is preferred as it returns null if the queue is empty
        String polledPerson = queue.poll();
        System.out.println("Removed by poll(): " + polledPerson); // Bob
        System.out.println("Queue after poll(): " + queue); // [Charlie, David]
        // --- Viewing Elements (Peeking) ---
        // element() will throw an exception if the queue is empty
        String headElement = queue.element();
        System.out.println("Head by element(): " + headElement); // Charlie
        // peek() is preferred as it returns null if the queue is empty
        String peekedElement = queue.peek();
        System.out.println("Head by peek(): " + peekedElement); // Charlie
        System.out.println("Queue after peek(): " + queue); // [Charlie, David] (unchanged)
    }
}

ArrayDeque

This is a modern, resizable array implementation of the Deque (Double-Ended Queue) interface. Since Deque extends Queue, it can be used as a standard queue. It is often faster than LinkedList and is the recommended default choice for most queue operations.

Characteristics:

  • Unbounded: Can grow as needed.
  • Resizable array: More memory-efficient than LinkedList for most use cases.
  • Fast: Generally offers better performance than LinkedList.
import java.util.ArrayDeque;
import java.util.Queue;
public class ArrayDequeQueueExample {
    public static void main(String[] args) {
        // Create a Queue using ArrayDeque
        Queue<Integer> queue = new ArrayDeque<>();
        // --- Adding Elements ---
        queue.offer(10);
        queue.offer(20);
        queue.offer(30);
        System.out.println("Queue: " + queue); // [10, 20, 30]
        // --- Removing Elements ---
        Integer removedNumber = queue.poll();
        System.out.println("Removed element: " + removedNumber); // 10
        System.out.println("Queue after poll: " + queue); // [20, 30]
        // --- Viewing Elements ---
        Integer head = queue.peek();
        System.out.println("Head of the queue: " + head); // 20
    }
}

PriorityQueue

A PriorityQueue is not a FIFO queue. It orders its elements based on their natural ordering or by a Comparator you provide. The element with the "highest priority" (e.g., the smallest number in a natural ordering) is at the head of the queue and is the first to be removed.

Characteristics:

  • Unbounded: Can grow as needed.
  • Not FIFO: Elements are ordered by priority, not insertion order.
  • Heap-based: Typically implemented using a heap data structure.
import java.util.PriorityQueue;
import java.util.Queue;
public class PriorityQueueExample {
    public static void main(String[] args) {
        // By default, PriorityQueue uses natural ordering (ascending for Integers)
        Queue<Integer> pq = new PriorityQueue<>();
        pq.offer(30);
        pq.offer(10);
        pq.offer(20);
        pq.offer(5);
        System.out.println("PriorityQueue: " + pq); // Note: The internal array isn't sorted, but the head is the smallest.
                                              // Output might look like: [5, 10, 20, 30] or [5, 10, 30, 20]
        // --- Removing Elements ---
        // poll() will always remove the element with the highest priority (the smallest number)
        System.out.println("Removed element: " + pq.poll()); // 5
        System.out.println("Removed element: " + pq.poll()); // 10
        System.out.println("Removed element: " + pq.poll()); // 20
        System.out.println("Removed element: " + pq.poll()); // 30
        // Example with custom objects
        Queue<Task> taskQueue = new PriorityQueue<>();
        taskQueue.add(new Task("Write report", 3)); // Lower number = higher priority
        taskQueue.add(new Task("Fix critical bug", 1));
        taskQueue.add(new Task("Update documentation", 5));
        System.out.println("\nProcessing tasks by priority:");
        while (!taskQueue.isEmpty()) {
            System.out.println("Processing: " + taskQueue.poll());
        }
    }
}
// A simple Task class to be used in the PriorityQueue
class Task implements Comparable<Task> {
    String name;
    int priority;
    public Task(String name, int priority) {
        this.name = name;
        this.priority = priority;
    }
    // Defines how tasks are compared (by priority)
    @Override
    public int compareTo(Task other) {
        return Integer.compare(this.priority, other.priority);
    }
    @Override
    public String toString() {
        return "Task{name='" + name + "', priority=" + priority + "}";
    }
}

When to Use Which Implementation?

Implementation When to Use It Key Feature
LinkedList When you need a simple, unbounded queue and might also need to remove from the back of the queue. Simple, flexible, also a Deque.
ArrayDeque (Recommended) For most general-purpose queue needs. It's faster and more memory-efficient than LinkedList. Fast, resizable array implementation.
PriorityQueue When order of processing is based on priority, not the order of insertion. Orders elements by natural or custom order.

Summary Table

Feature LinkedList ArrayDeque PriorityQueue
Interface Queue, Deque Deque Queue
Ordering FIFO FIFO Priority-based
Performance Good Excellent Good (logarithmic for add/remove)
Memory Higher (more overhead) Lower (more compact) Lower
Use Case General purpose, also good as a deque Default choice for queues Task scheduling, event handling
分享:
扫描分享到社交APP
上一篇
下一篇