Java Queue Interface


In Java, the Queue interface is part of the java.util package and represents a collection designed for holding elements prior to processing. It is an essential part of the Java Collections Framework and defines a collection that operates on the First-In-First-Out (FIFO) principle. This means that the first element added to the queue will be the first one to be removed, similar to how people queue up in line.

Queues are commonly used in various applications such as task scheduling, data buffering, and managing resources. In this blog post, we will explore the Queue interface, its common implementations, methods, and provide practical examples to help you understand how to work with queues in Java.


What is the Java Queue Interface?

A queue is a linear data structure that allows elements to be inserted at the back and removed from the front, adhering to the FIFO (First-In-First-Out) principle. The Queue interface in Java extends the Collection interface and provides a contract for various queue operations.

The Queue interface supports the following fundamental operations:

  • Offer: Adds an element to the queue.
  • Poll: Removes and returns the element at the front of the queue.
  • Peek: Returns the element at the front of the queue without removing it.

Unlike a List, a queue does not allow random access to its elements. Instead, elements are processed in the order they were added.


Key Methods of the Java Queue Interface

Here are some of the essential methods of the Queue interface:

  • offer(E e): Inserts the specified element into the queue. Returns true if successful.
  • poll(): Removes and returns the element at the front of the queue. Returns null if the queue is empty.
  • peek(): Returns the element at the front of the queue without removing it. Returns null if the queue is empty.
  • remove(): Removes and returns the front element of the queue. Throws NoSuchElementException if the queue is empty.
  • size(): Returns the number of elements in the queue.
  • isEmpty(): Checks if the queue is empty.

Common Implementations of the Java Queue Interface

Several classes in the Java Collections Framework implement the Queue interface, each suited for different use cases:

  1. LinkedList: A doubly linked list that can be used as a queue. It supports efficient insertion and removal of elements at both ends.
  2. PriorityQueue: A queue where elements are ordered based on their priority. It does not follow FIFO order but instead uses a comparator or the natural ordering of elements.
  3. ArrayDeque: A resizable array implementation of a deque (double-ended queue). It is faster than LinkedList for most use cases and does not allow null elements.
  4. BlockingQueue: Part of the java.util.concurrent package, a BlockingQueue can be used in multi-threaded applications to block the thread until an element becomes available or space becomes available in the queue.

Using the Java Queue Interface: Code Examples

Let’s look at practical examples using common queue implementations.

Example 1: Using LinkedList as a Queue

The LinkedList class implements the Queue interface and provides the FIFO behavior that is typical of a queue.

import java.util.LinkedList;
import java.util.Queue;

public class Main {
    public static void main(String[] args) {
        Queue<String> queue = new LinkedList<>();

        // Adding elements to the queue
        queue.offer("Apple");
        queue.offer("Banana");
        queue.offer("Cherry");

        // Displaying the queue
        System.out.println("Queue: " + queue);

        // Removing and printing the front element
        String removedElement = queue.poll();
        System.out.println("Removed Element: " + removedElement);

        // Displaying the queue after removal
        System.out.println("Queue after poll: " + queue);

        // Peeking at the front element
        String front = queue.peek();
        System.out.println("Front Element: " + front);
    }
}

Output:

Queue: [Apple, Banana, Cherry]
Removed Element: Apple
Queue after poll: [Banana, Cherry]
Front Element: Banana

Example 2: Using PriorityQueue

A PriorityQueue allows elements to be processed according to their priority rather than in FIFO order. The elements are ordered using their natural ordering or a custom comparator.

import java.util.PriorityQueue;
import java.util.Queue;

public class Main {
    public static void main(String[] args) {
        Queue<Integer> priorityQueue = new PriorityQueue<>();

        // Adding elements with different priorities
        priorityQueue.offer(20);
        priorityQueue.offer(10);
        priorityQueue.offer(30);

        // Displaying the queue
        System.out.println("Priority Queue: " + priorityQueue);

        // Removing and printing the front element (highest priority)
        Integer removedElement = priorityQueue.poll();
        System.out.println("Removed Element: " + removedElement);

        // Displaying the queue after removal
        System.out.println("Priority Queue after poll: " + priorityQueue);
    }
}

Output:

Priority Queue: [10, 20, 30]
Removed Element: 10
Priority Queue after poll: [20, 30]

Example 3: Using ArrayDeque

An ArrayDeque is a highly efficient queue implementation. Unlike LinkedList, ArrayDeque does not allow null elements and generally performs better for most use cases.

import java.util.ArrayDeque;
import java.util.Queue;

public class Main {
    public static void main(String[] args) {
        Queue<String> queue = new ArrayDeque<>();

        // Adding elements to the queue
        queue.offer("Red");
        queue.offer("Green");
        queue.offer("Blue");

        // Displaying the queue
        System.out.println("Queue: " + queue);

        // Removing and printing the front element
        String removedElement = queue.poll();
        System.out.println("Removed Element: " + removedElement);

        // Displaying the queue after removal
        System.out.println("Queue after poll: " + queue);
    }
}

Output:

Queue: [Red, Green, Blue]
Removed Element: Red
Queue after poll: [Green, Blue]

When to Use a Queue in Java?

Queues are used in various scenarios, such as:

  • Task Scheduling: Managing tasks to be processed by workers in a multi-threaded environment.
  • Breadth-First Search (BFS): Implementing BFS in graph traversal algorithms, where nodes are explored level by level.
  • Print Spooler: Managing print jobs, where jobs are printed in the order they were submitted.
  • Message Queues: Handling messages in messaging systems (e.g., RabbitMQ, Kafka).

Queue vs. Other Data Structures

  • Queue vs. Stack: A queue operates in FIFO order, while a stack follows the LIFO (Last-In-First-Out) principle.
  • Queue vs. List: A List allows random access to elements and does not enforce an ordering of element removal like a queue.
  • Queue vs. Deque: A Deque (double-ended queue) allows adding/removing elements from both ends, while a queue only supports removal from one end.