Skip to Content
Course content

198: Working with Deque as Stack and Queue

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Why am I being told to avoid the Stack class?

If you look at the Java API, you'll see a class literally called Stack. It seems like the obvious choice, right? But here's the deal: Stack is a legacy class. It extends Vector, which means it's synchronized. In most modern applications, you don't need that overhead on every single push and pop operation. It also inherits methods from Vector that don't make sense for a stack—like the ability to insert an element at a specific index. That breaks the whole "Last-In, First-Out" (LIFO) contract.

I always recommend using Deque (Double Ended Queue) instead. It's an interface, and the ArrayDeque implementation is significantly faster and more consistent. When you use Deque, you're explicitly choosing whether you want stack behavior or queue behavior based on the methods you call.

Which methods actually turn a Deque into a Queue?

When you're using a Deque as a queue, you're following "First-In, First-Out" (FIFO) logic. Think of it like a line at a coffee shop: the first person to get in line is the first person served. To achieve this, you add to the tail and remove from the head.

You have two sets of methods: those that throw exceptions and those that return special values (like null). I usually prefer the "safe" versions (offer/poll) to avoid crashing the app over an empty collection.

Deque<String> printQueue = new ArrayDeque<>();

// Adding tasks to the end of the line
printQueue.offer("Quarterly_Report.pdf");
printQueue.offer("Vacation_Photo.jpg");
printQueue.offer("Resume_Final_v2.pdf");

// Processing the first item in line
while (!printQueue.isEmpty()) {
    String document = printQueue.poll(); 
    System.out.println("Printing: " + document);
}

In this example, offer() puts the item at the back, and poll() grabs it from the front. Simple and clean.

How do I use it as a Stack without getting confused?

To use a Deque as a stack, you want "Last-In, First-Out" (LIFO). Imagine a stack of dinner plates; you put the last plate on top and you take that same plate off first. For this, you operate exclusively on the front of the deque.

Java provides push() and pop() specifically to make the Deque interface feel like a traditional stack. Under the hood, push() is just a shortcut for addFirst().

Deque<String> browserHistory = new ArrayDeque<>();

// Navigating to pages
browserHistory.push("google.com");
browserHistory.push("github.com");
browserHistory.push("stackoverflow.com");

// User hits the 'Back' button
String lastPage = browserHistory.pop(); 
System.out.println("Returning to: " + lastPage); // Returns stackoverflow.com

One thing to watch out for: pop() will throw a NoSuchElementException if the deque is empty. I always suggest checking isEmpty() first, or using pollFirst() if you'd rather get a null back than an exception.

Can I mix both behaviors in one object?

Technically, yes, because it's a Deque. But honestly? Don't do it. If you start pushing elements to the front and polling them from the back, and then suddenly decide to pop from the front, your code becomes a nightmare to debug. Your teammates (and your future self) will have no idea if the collection is supposed to be a stack or a queue.

If you need both behaviors, you're likely building something more complex, like a sliding window cache or a work-stealing algorithm. In those cases, stop thinking in terms of "Stack" or "Queue" and start using the explicit addFirst(), addLast(), removeFirst(), and removeLast() methods. It makes your intention crystal clear to anyone reading the code.




📋 Practical Task

Exercise: Build a Text Editor Undo-Redo Buffer

You are building a simplified text editor. You need to implement a system that tracks the history of "actions" (represented as Strings) so the user can undo their mistakes. However, to save memory, the buffer should only hold the last 10 actions.

Requirements:

  • Use an ArrayDeque to store the actions.
  • Implement a method performAction(String action) that adds a new action to the top of the stack.
  • Implement a method undo() that removes and returns the most recent action.
  • The Twist: Inside performAction, check if the deque size exceeds 10. If it does, remove the oldest action from the bottom of the stack to make room for the new one.

Test your implementation by adding 12 different actions and then performing 3 undos. Verify that the oldest two actions were discarded and you are undoing the 12th, 11th, and 10th actions respectively.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.