Queue in Java
Learn about First-In-First-Out (FIFO) collections
💡 Think of a Queue like a line at a store - the first person who gets in line is the first person to be served! People join at the back of the line and leave from the front. It's fair because everyone waits their turn in order!
🚶 What is a Queue?
A Queue is a collection designed for holding elements before processing. It follows the FIFO (First-In-First-Out) principle. Elements are added at the tail (rear) and removed from the head (front). Think of it like a waiting line!
import java.util.LinkedList;import java.util.Queue;public class BasicQueue { public static void main(String[] args) { // Creating a Queue using LinkedList Queue<String> queue = new LinkedList<>(); // Adding elements to the queue (at the tail) queue.offer("First"); queue.offer("Second"); queue.offer("Third"); queue.offer("Fourth"); System.out.println("Queue: " + queue); // [First, Second, Third, Fourth] // Peek at the front element (without removing) String front = queue.peek(); System.out.println("Front element: " + front); // First System.out.println("Queue after peek: " + queue); // Unchanged // Remove and get the front element String removed1 = queue.poll(); // Removes "First" System.out.println("Removed: " + removed1); System.out.println("Queue after poll: " + queue); // [Second, Third, Fourth] // Continue removing queue.poll(); // Removes "Second" System.out.println("After second poll: " + queue); // [Third, Fourth] // Size and empty check System.out.println("\nQueue size: " + queue.size()); System.out.println("Is empty? " + queue.isEmpty()); // Poll from empty queue returns null queue.poll(); // Removes "Third" queue.poll(); // Removes "Fourth" String fromEmpty = queue.poll(); // Queue is now empty System.out.println("\nPolling empty queue: " + fromEmpty); // null }}🔍 📋 Types of Queues
Java provides different Queue implementations for different scenarios:
LinkedList
Most common Queue implementation, allows null elements, implements both Queue and Deque
PriorityQueue
Elements ordered by priority (natural order or comparator), not strictly FIFO
ArrayDeque
Faster than LinkedList, no null elements, implements Deque interface
PriorityBlockingQueue
Thread-safe version of PriorityQueue for concurrent programming
import java.util.PriorityQueue;import java.util.Queue;public class PriorityQueueExample { public static void main(String[] args) { // PriorityQueue orders elements by natural order (or comparator) Queue<Integer> priorityQueue = new PriorityQueue<>(); // Add elements in random order priorityQueue.offer(5); priorityQueue.offer(2); priorityQueue.offer(8); priorityQueue.offer(1); priorityQueue.offer(3); System.out.println("PriorityQueue: " + priorityQueue); // NOTE: Internal order may look random, but poll() gives sorted order // Elements come out in sorted order (lowest first) System.out.println("\nRemoving elements in priority order:"); while (!priorityQueue.isEmpty()) { System.out.println(priorityQueue.poll()); } // Output: 1, 2, 3, 5, 8 // PriorityQueue with custom comparator (reverse order) Queue<Integer> maxHeap = new PriorityQueue<>((a, b) -> b - a); maxHeap.offer(5); maxHeap.offer(2); maxHeap.offer(8); maxHeap.offer(1); System.out.println("\nMax heap (highest priority first):"); while (!maxHeap.isEmpty()) { System.out.println(maxHeap.poll()); } // Output: 8, 5, 2, 1 }}🖨️ Real-World Example: Printer Queue
import java.util.LinkedList;import java.util.Queue;class PrintJob { String documentName; int pages; public PrintJob(String documentName, int pages) { this.documentName = documentName; this.pages = pages; } @Override public String toString() { return documentName + " (" + pages + " pages)"; }}public class PrinterQueue { private Queue<PrintJob> printQueue; public PrinterQueue() { this.printQueue = new LinkedList<>(); } // Add print job to queue public void addPrintJob(String documentName, int pages) { PrintJob job = new PrintJob(documentName, pages); printQueue.offer(job); System.out.println("Added to queue: " + job); } // Process next print job public void printNext() { if (printQueue.isEmpty()) { System.out.println("No documents in queue!"); return; } PrintJob job = printQueue.poll(); System.out.println("\nPrinting: " + job); System.out.println("Remaining jobs: " + printQueue.size()); } // View next job without printing public void viewNext() { PrintJob job = printQueue.peek(); if (job != null) { System.out.println("Next in queue: " + job); } else { System.out.println("Queue is empty!"); } } // View all pending jobs public void viewAllJobs() { if (printQueue.isEmpty()) { System.out.println("\nNo pending jobs"); return; } System.out.println("\n=== Print Queue ==="); int position = 1; for (PrintJob job : printQueue) { System.out.println(position++ + ". " + job); } System.out.println("Total jobs: " + printQueue.size()); } public static void main(String[] args) { PrinterQueue printer = new PrinterQueue(); // Add print jobs printer.addPrintJob("Report.pdf", 10); printer.addPrintJob("Presentation.pptx", 25); printer.addPrintJob("Invoice.docx", 3); printer.addPrintJob("Photo.jpg", 1); // View all jobs printer.viewAllJobs(); // View next job printer.viewNext(); // Process jobs printer.printNext(); printer.printNext(); // View remaining jobs printer.viewAllJobs(); // Print remaining jobs printer.printNext(); printer.printNext(); // Try to print when empty printer.printNext(); }}⏰ Real-World Example: Task Scheduler
import java.util.ArrayDeque;import java.util.Deque;class Task { String name; int estimatedMinutes; public Task(String name, int estimatedMinutes) { this.name = name; this.estimatedMinutes = estimatedMinutes; } @Override public String toString() { return name + " (~" + estimatedMinutes + " min)"; }}public class TaskScheduler { private Deque<Task> taskQueue; public TaskScheduler() { // Using ArrayDeque (faster than LinkedList) this.taskQueue = new ArrayDeque<>(); } // Add task to end of queue public void addTask(String name, int minutes) { Task task = new Task(name, minutes); taskQueue.offerLast(task); System.out.println("Scheduled: " + task); } // Add urgent task to front of queue public void addUrgentTask(String name, int minutes) { Task task = new Task(name, minutes); taskQueue.offerFirst(task); System.out.println("URGENT - Added to front: " + task); } // Complete next task public void completeNextTask() { if (taskQueue.isEmpty()) { System.out.println("No tasks to complete!"); return; } Task task = taskQueue.pollFirst(); System.out.println("\nCompleted: " + task); System.out.println("Remaining tasks: " + taskQueue.size()); } // Remove last task (undo scheduling) public void removeLastScheduled() { Task task = taskQueue.pollLast(); if (task != null) { System.out.println("Removed: " + task); } } // View all tasks public void viewTasks() { if (taskQueue.isEmpty()) { System.out.println("\nNo scheduled tasks"); return; } System.out.println("\n=== Task Schedule ==="); int totalMinutes = 0; int position = 1; for (Task task : taskQueue) { System.out.println(position++ + ". " + task); totalMinutes += task.estimatedMinutes; } System.out.println("\nTotal tasks: " + taskQueue.size()); System.out.println("Estimated time: " + totalMinutes + " minutes"); } public static void main(String[] args) { TaskScheduler scheduler = new TaskScheduler(); // Schedule normal tasks scheduler.addTask("Write email", 15); scheduler.addTask("Team meeting", 30); scheduler.addTask("Code review", 45); scheduler.addTask("Lunch break", 60); // View schedule scheduler.viewTasks(); // Urgent task comes in! scheduler.addUrgentTask("Fix critical bug", 20); // View updated schedule scheduler.viewTasks(); // Complete tasks scheduler.completeNextTask(); // Fix critical bug scheduler.completeNextTask(); // Write email // Cancel last task scheduler.removeLastScheduled(); // Remove lunch break // View final schedule scheduler.viewTasks(); }}🏥 Real-World Example: Hospital Emergency Room
import java.util.PriorityQueue;import java.util.Queue;class Patient implements Comparable<Patient> { String name; int severity; // 1 = Critical, 2 = Serious, 3 = Moderate, 4 = Minor public Patient(String name, int severity) { this.name = name; this.severity = severity; } // Lower severity number = higher priority @Override public int compareTo(Patient other) { return Integer.compare(this.severity, other.severity); } @Override public String toString() { String level = switch (severity) { case 1 -> "CRITICAL"; case 2 -> "SERIOUS"; case 3 -> "MODERATE"; default -> "MINOR"; }; return name + " [" + level + "]"; }}public class EmergencyRoom { private Queue<Patient> waitingRoom; public EmergencyRoom() { this.waitingRoom = new PriorityQueue<>(); } // Register patient public void registerPatient(String name, int severity) { Patient patient = new Patient(name, severity); waitingRoom.offer(patient); System.out.println("Registered: " + patient); } // Treat next patient (highest priority) public void treatNextPatient() { if (waitingRoom.isEmpty()) { System.out.println("No patients waiting!"); return; } Patient patient = waitingRoom.poll(); System.out.println("\nTreating: " + patient); System.out.println("Patients waiting: " + waitingRoom.size()); } // View next patient public void viewNext() { Patient patient = waitingRoom.peek(); if (patient != null) { System.out.println("Next patient: " + patient); } else { System.out.println("No patients waiting"); } } // View all waiting patients public void viewAllPatients() { if (waitingRoom.isEmpty()) { System.out.println("\nNo patients waiting"); return; } System.out.println("\n=== Waiting Room ==="); // Create copy to preserve queue Queue<Patient> copy = new PriorityQueue<>(waitingRoom); int position = 1; while (!copy.isEmpty()) { System.out.println(position++ + ". " + copy.poll()); } System.out.println("Total waiting: " + waitingRoom.size()); } public static void main(String[] args) { EmergencyRoom er = new EmergencyRoom(); // Patients arrive in random order er.registerPatient("John (broken arm)", 3); // Moderate er.registerPatient("Sarah (heart attack)", 1); // Critical! er.registerPatient("Mike (flu)", 4); // Minor er.registerPatient("Emma (car accident)", 2); // Serious er.registerPatient("Tom (cut finger)", 4); // Minor // View all patients (in priority order) er.viewAllPatients(); // Treat patients - critical cases first! System.out.println("\n--- Starting Treatment ---"); er.treatNextPatient(); // Sarah (critical) er.treatNextPatient(); // Emma (serious) er.treatNextPatient(); // John (moderate) // View remaining er.viewAllPatients(); // New critical patient arrives! er.registerPatient("Alice (severe bleeding)", 1); er.viewNext(); // Alice goes to front! er.treatNextPatient(); // Alice er.treatNextPatient(); // Mike er.treatNextPatient(); // Tom }}🔄 Queue Methods Comparison
import java.util.LinkedList;import java.util.Queue;public class QueueMethods { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); // ===== ADDING ELEMENTS ===== // add() - throws exception if fails (for bounded queues) queue.add("A"); queue.add("B"); // offer() - returns false if fails (safer) boolean success = queue.offer("C"); System.out.println("Offer successful? " + success); // true System.out.println("Queue: " + queue); // [A, B, C] // ===== RETRIEVING WITHOUT REMOVING ===== // element() - throws NoSuchElementException if empty String head1 = queue.element(); System.out.println("\nelement(): " + head1); // A // peek() - returns null if empty (safer) String head2 = queue.peek(); System.out.println("peek(): " + head2); // A System.out.println("Queue unchanged: " + queue); // [A, B, C] // ===== RETRIEVING AND REMOVING ===== // remove() - throws NoSuchElementException if empty String removed1 = queue.remove(); System.out.println("\nremove(): " + removed1); // A // poll() - returns null if empty (safer) String removed2 = queue.poll(); System.out.println("poll(): " + removed2); // B System.out.println("Queue after removals: " + queue); // [C] // ===== TESTING WITH EMPTY QUEUE ===== queue.poll(); // Remove last element System.out.println("\nQueue is now empty"); // Safe methods return null System.out.println("peek() on empty: " + queue.peek()); // null System.out.println("poll() on empty: " + queue.poll()); // null // Unsafe methods throw exceptions try { queue.element(); // Throws NoSuchElementException } catch (Exception e) { System.out.println("element() threw: " + e.getClass().getSimpleName()); } try { queue.remove(); // Throws NoSuchElementException } catch (Exception e) { System.out.println("remove() threw: " + e.getClass().getSimpleName()); } // ===== BEST PRACTICE ===== System.out.println("\n=== Best Practice ==="); System.out.println("Use offer(), poll(), peek() for safer code!"); }}🔑 Key Concepts
FIFO Order
First element added is the first one removed
Add [A, B, C] → Remove gets A, then B, then C
offer() vs add()
offer() returns false if fails, add() throws exception
Use offer() for bounded queues, add() for unbounded
poll() vs remove()
poll() returns null if empty, remove() throws exception
Use poll() to safely check empty queue
peek() vs element()
peek() returns null if empty, element() throws exception
peek() lets you look at front without removing
✨ Best Practices
- ✓Use LinkedList for simple FIFO queues
- ✓Use ArrayDeque for better performance (faster than LinkedList)
- ✓Use PriorityQueue when elements need priority-based ordering
- ✓Prefer offer()/poll()/peek() over add()/remove()/element() for safer code
- ✓Don't add null to queues (ArrayDeque and PriorityQueue don't allow it)
- ✓Use Deque interface when you need both queue and stack operations
- ✓Consider BlockingQueue for producer-consumer patterns in multithreading
💼 Interview Tips
- •Queue is an interface, not a class - use LinkedList or ArrayDeque
- •PriorityQueue uses heap (binary tree) internally - O(log n) for add/remove
- •ArrayDeque is faster than LinkedList (no node overhead)
- •PriorityQueue doesn't allow null, but LinkedList does
- •Deque (Double-Ended Queue) can work as both queue and stack
- •Know the difference between Deque methods: addFirst/addLast, pollFirst/pollLast
- •Understanding when to use which queue type is important
- •Remember that PriorityQueue is NOT thread-safe