A Circular Queue (also called a Ring Buffer) is a queue data structure that treats its underlying array as if it were connected end-to-end in a circle. Unlike a linear queue, once the rear pointer reaches the end of the array, it wraps back to index 0 — allowing reuse of freed slots without shifting elements.
This post implements a true circular queue in Java using an array, with proper wraparound logic for both the front and rear pointers.
How a Circular Queue Works
- Both
frontandrearstart at-1(empty state). - Enqueue: Advance
rearwith wraparound:rear = (rear + 1) % size. The queue is full when(rear + 1) % size == front. - Dequeue: Advance
frontwith wraparound:front = (front + 1) % size. Reset both to-1when the last element is removed. - Circular property: Elements can be added to index 0 again after
fronthas moved past it.
Java Program: Circular Queue
import java.io.*;
// Circular queue backed by a fixed-size array
class CircularQueue {
int item[]; // Array holding queue elements
int front; // Index of the front element
int rear; // Index of the rear element
int size; // Maximum capacity
public CircularQueue(int capacity) {
item = new int[capacity];
front = rear = -1; // -1 indicates empty queue
size = capacity;
}
// Returns true if the queue is full
public boolean isFull() {
return (front == 0 && rear == size - 1)
|| (rear == (front - 1) % (size - 1));
}
// Returns true if the queue is empty
public boolean isEmpty() {
return (front == -1);
}
// Adds an element to the rear of the queue
public void enqueue(int element) {
if (isFull()) {
System.out.println("Queue is full");
} else {
if (front == -1) {
// First element: initialise both pointers to 0
front = 0;
rear = 0;
} else if (rear == size - 1 && front != 0) {
// Rear has reached end of array; wrap around to beginning
rear = 0;
} else {
rear++;
}
item[rear] = element;
}
}
// Removes and returns the front element
public int dequeue() {
if (isEmpty()) {
System.out.println("Queue is empty");
return -1;
}
int removedElement = item[front];
if (front == rear) {
// Last element removed; reset to empty state
front = rear = -1;
} else if (front == size - 1) {
// Front was at last index; wrap around
front = 0;
} else {
front++;
}
return removedElement;
}
// Returns the front element without removing it
public int peek() {
if (isEmpty()) {
System.out.println("Queue is empty");
return -1;
}
return item[front];
}
// Displays all elements from front to rear
public void display() {
if (isEmpty()) {
System.out.println("Queue is empty");
return;
}
System.out.print("Queue: ");
if (rear >= front) {
// Normal case: no wraparound
for (int i = front; i <= rear; i++) {
System.out.print(item[i] + " ");
}
} else {
// Wrapped: print from front to end, then 0 to rear
for (int i = front; i < size; i++) {
System.out.print(item[i] + " ");
}
for (int i = 0; i <= rear; i++) {
System.out.print(item[i] + " ");
}
}
System.out.println();
}
}
public class CircularQueueDemo {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter size of queue: ");
int size = Integer.parseInt(reader.readLine());
CircularQueue queue = new CircularQueue(size);
int choice;
do {
System.out.println();
System.out.println("--- Circular Queue Menu ---");
System.out.println("1. Enqueue (add element)");
System.out.println("2. Dequeue (remove element)");
System.out.println("3. Display queue");
System.out.println("4. Peek (front element)");
System.out.println("5. Exit");
System.out.print("Enter choice: ");
choice = Integer.parseInt(reader.readLine());
switch (choice) {
case 1:
System.out.print("Enter element to add: ");
int element = Integer.parseInt(reader.readLine());
queue.enqueue(element);
break;
case 2:
int removed = queue.dequeue();
if (removed != -1) System.out.println("Removed: " + removed);
break;
case 3:
queue.display();
break;
case 4:
int front = queue.peek();
if (front != -1) System.out.println("Front element: " + front);
break;
case 5:
System.out.println("Exiting...");
break;
default:
System.out.println("Invalid choice");
}
} while (choice != 5);
}
}
How the Code Works
- CircularQueue class — Wraps an integer array with
front,rear, andsizefields. Both pointers start at-1. - isFull() — Returns
truewhen the slot just afterrear(circularly) equalsfront, meaning no free slots remain. - enqueue() — On the first insert, sets both
frontandrearto 0. On subsequent inserts, incrementsrear, wrapping it to 0 when it hits the array end. - dequeue() — Returns and removes the element at
front, then advancesfrontwith wraparound. When the last element is removed, both pointers reset to-1. - display() — Handles both the normal case (rear ≥ front) and the wrapped case (rear < front) to print all elements in queue order.
Sample Output
Enter size of queue: 5
--- Circular Queue Menu ---
1. Enqueue (add element)
2. Dequeue (remove element)
3. Display queue
4. Peek (front element)
5. Exit
Enter choice: 1
Enter element to add: 10
--- Circular Queue Menu ---
1. Enqueue (add element)
2. Dequeue (remove element)
3. Display queue
4. Peek (front element)
5. Exit
Enter choice: 1
Enter element to add: 20
--- Circular Queue Menu ---
1. Enqueue (add element)
2. Dequeue (remove element)
3. Display queue
4. Peek (front element)
5. Exit
Enter choice: 1
Enter element to add: 30
--- Circular Queue Menu ---
1. Enqueue (add element)
2. Dequeue (remove element)
3. Display queue
4. Peek (front element)
5. Exit
Enter choice: 1
Enter element to add: 40
--- Circular Queue Menu ---
1. Enqueue (add element)
2. Dequeue (remove element)
3. Display queue
4. Peek (front element)
5. Exit
Enter choice: 1
Enter element to add: 50
--- Circular Queue Menu ---
1. Enqueue (add element)
2. Dequeue (remove element)
3. Display queue
4. Peek (front element)
5. Exit
Enter choice: 1
Enter element to add: 60
Queue is full
--- Circular Queue Menu ---
1. Enqueue (add element)
2. Dequeue (remove element)
3. Display queue
4. Peek (front element)
5. Exit
Enter choice: 3
Queue: 10 20 30 40 50
--- Circular Queue Menu ---
1. Enqueue (add element)
2. Dequeue (remove element)
3. Display queue
4. Peek (front element)
5. Exit
Enter choice: 4
Front element: 10
--- Circular Queue Menu ---
1. Enqueue (add element)
2. Dequeue (remove element)
3. Display queue
4. Peek (front element)
5. Exit
Enter choice: 2
Removed: 10
--- Circular Queue Menu ---
1. Enqueue (add element)
2. Dequeue (remove element)
3. Display queue
4. Peek (front element)
5. Exit
Enter choice: 2
Removed: 20
--- Circular Queue Menu ---
1. Enqueue (add element)
2. Dequeue (remove element)
3. Display queue
4. Peek (front element)
5. Exit
Enter choice: 3
Queue: 30 40 50
--- Circular Queue Menu ---
1. Enqueue (add element)
2. Dequeue (remove element)
3. Display queue
4. Peek (front element)
5. Exit
Enter choice: 5
Exiting...
Output Explanation
- With a capacity of 5, the fifth enqueue fills the queue. The sixth attempt correctly prints Queue is full.
- After dequeuing 10 and 20, the front pointer advances — and the freed slots at indices 0 and 1 become available for future insertions (the circular advantage).
- The display correctly shows the remaining elements 30 40 50 in FIFO order.
See Also
- Implementing Circular Queue in Java with Arrays — An alternate implementation of circular queue
- Java Implementation of Queue using Linked List — A dynamically-sized queue using linked nodes
- Implementation of Stack in Java — The LIFO counterpart to a queue
Conclusion
Circular queues solve the key limitation of a linear array queue — wasted space at the front after dequeue operations. By wrapping the pointers around, the same array can be reused indefinitely. Circular queues are widely used in operating system buffers, I/O stream processing, and producer-consumer problems where a fixed-size buffer is shared between threads.