Stacks and queues define which stored element is removed next. A stack follows last-in, first-out order, useful for undo actions and nested structure checking. A queue follows first-in, first-out order, useful for ordinary waiting lines. In modern Java, ArrayDeque is a convenient implementation for both behaviors through the Deque interface. Learn the operation names and empty-container contracts carefully so a program does not accidentally mix stack removal with queue insertion.
Stack operations use one end
push adds at the front, pop removes from the front, and peek inspects the front without removal. The newest pushed item is therefore the first popped. Deque offers this stack vocabulary without requiring the older Stack class. A stack can model returning through nested work because the most recent unresolved operation is handled first. Keep the chosen vocabulary consistent instead of mixing front and back methods without explaining the intended order.
Queue operations use opposite ends
offer adds at the tail and poll removes from the head for a FIFO queue. peek reads the head without removal. This preserves arrival order. Queue defines both exception-throwing and special-value forms: remove throws for an empty queue, while poll returns null. ArrayDeque rejects null elements, making that null result unambiguous as absence. Capacity behavior differs for bounded queue implementations, so do not infer every Queue accepts an unlimited number of offers.
Select the empty-container policy
For a task dispatcher, an empty queue can be a normal condition, so poll may be convenient. For a stack where an item is required by an invariant, pop's NoSuchElementException may reveal a violated assumption. Check isEmpty before removing when that is appropriate in single-threaded code. In concurrent code, a separate check followed by removal can race, so use a suitable concurrent collection and its atomic operation rather than assuming the check reserves an item.
Use ArrayDeque for ordinary local work
ArrayDeque provides resizable-array storage with efficient operations at both ends. It is not thread-safe, and it rejects null. It is usually a suitable default for a local stack or FIFO queue. It does not provide efficient arbitrary indexing like ArrayList. LinkedList also implements Deque, but its node storage has different overhead. Select the abstraction from the removal policy, then choose an implementation matching concurrency and capacity requirements.
Recognize where a stack solves nesting
Matching brackets illustrates the stack's purpose. Each opening bracket creates an unresolved requirement; a closing bracket must match the most recent opening. If the stack is empty at a closing bracket, the input closes something that was never opened. If openings remain afterward, the input is incomplete. Handling different bracket types requires comparing the pair, not merely counting openings and closings. A count alone cannot detect crossed nesting.
Do not confuse a priority queue with FIFO
PriorityQueue removes according to priority ordering, not arrival order. It is useful for scheduling the smallest or highest-priority next item under a comparator, but it is a different contract from a waiting line. Its iteration order is also not a sorted traversal. When order matters, identify whether it means arrival, latest action, or priority before selecting Queue simply because all three data structures store pending values.
Practice tasks and checks
Add a third action to UndoStack and predict all removals before running it. Replace pop with peek once and confirm the size does not decrease. For ServiceQueue, handle a null result with a clear empty message rather than printing null. Extend ParenthesisStack to square brackets and test nested input such as ([a]) and crossed input such as ([)]. The crossed input must fail even though the counts match. Finally, explain which application fits each policy: undo history, ticket arrival, and urgent-task scheduling. Use a stack, FIFO queue, and priority queue respectively, and document whether your implementation is local or shared between threads. The ordering contract should drive the choice.
Java Summary
- Stacks remove the newest item; FIFO queues remove the oldest.
- Use ArrayDeque operation names consistently with the intended policy.
- Choose an explicit response to an empty container.
- Continue with collection choices when these examples are clear.
Java Examples
Each example shows the code, the output it produces and what each part does.
Undo in reverse order
Save this program as UndoStack.java. Compile it with javac UndoStack.java and run it with java UndoStack.
Expected output:
The image action was pushed most recently, so pop returns it first. The heading action follows, and the stack is then empty. This is the ordering needed to undo changes in reverse sequence. The example stores descriptions rather than executable undo commands; a real editor would store enough information to reverse each operation. peek would read the next action without changing the remaining stack.
import java.util.ArrayDeque;
import java.util.Deque;
public class UndoStack {
public static void main(String[] args) {
Deque<String> actions = new ArrayDeque<>();
actions.push("Add heading");
actions.push("Add image");
System.out.println(actions.pop());
System.out.println(actions.pop());
System.out.println(actions.isEmpty());
}
}Add image
Add heading
trueServe customers in arrival order
Save this program as ServiceQueue.java. Compile it with javac ServiceQueue.java and run it with java ServiceQueue.
Expected output:
offer places Mina before Omar in arrival order. The first two poll calls remove those values in that same order. The third finds no value and returns null instead of throwing. Printing null here demonstrates the contract; a user interface should normally display a meaningful empty-line message instead. No null element was stored, because ArrayDeque does not allow one.
import java.util.ArrayDeque;
import java.util.Queue;
public class ServiceQueue {
public static void main(String[] args) {
Queue<String> line = new ArrayDeque<>();
line.offer("Mina");
line.offer("Omar");
System.out.println(line.poll());
System.out.println(line.poll());
System.out.println(line.poll());
}
}Mina
Omar
nullCheck parentheses with a stack
Save this program as ParenthesisStack.java. Compile it with javac ParenthesisStack.java and run it with java ParenthesisStack.
Expected output:
Each opening parenthesis is pushed, and each closing parenthesis removes the most recent unresolved opening. The first expression removes every opening in valid order. The second begins with a closing parenthesis, so it fails immediately even though counting alone might suggest a later opening could compensate. Nonparenthesis characters are ignored by this limited checker. Supporting square and curly brackets requires storing and verifying their types too.
import java.util.ArrayDeque;
import java.util.Deque;
public class ParenthesisStack {
static boolean balanced(String text) {
Deque<Character> openings = new ArrayDeque<>();
for (char symbol : text.toCharArray()) {
if (symbol == '(') openings.push(symbol);
else if (symbol == ')') {
if (openings.isEmpty()) return false;
openings.pop();
}
}
return openings.isEmpty();
}
public static void main(String[] args) {
System.out.println(balanced("(a+(b))"));
System.out.println(balanced(")(a"));
}
}true
falseJava FAQ
Should I use java.util.Stack?
For ordinary new local stack code, Deque with ArrayDeque is generally clearer and avoids the older Vector-based Stack design. Choose another implementation when its documented concurrency or capacity contract is required.
Does peek remove an element?
No. It inspects the next element under the container's ordering rule. Removal uses pop for the stack vocabulary or poll for the queue vocabulary shown here.
What happens if I pop from an empty ArrayDeque?
pop() and remove() throw NoSuchElementException, while poll() returns null. Use pop when an empty stack means a bug, and poll when emptiness is a normal situation to check for.
Can an ArrayDeque store null?
No. Adding null throws NullPointerException, because methods such as poll and peek use null to mean "the deque is empty". Store a placeholder object or an Optional if you need to represent "no value".
Where are stacks and queues used in real programs?
Stacks power undo and redo, the browser's back button, expression evaluation and the call stack that tracks method calls. Queues handle print jobs, customer support tickets, message processing between services and breadth-first search through graphs.
Java Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Which action is removed first from UndoStack?
What does poll return on an empty ArrayDeque queue?
Java Quiz
2 questions to check what you learned.
Why does )(a fail the parentheses checker?
- It closes before any opening is available
- It contains a letter
- All expressions need two pairs
Which structure follows priority rather than arrival order?
- PriorityQueue
- ArrayDeque used as FIFO
- An ordinary waiting line