Java
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented Java
-
Section 4: Collections Framework
-
Section 5: Exception Handling
-
Section 6: Generics
-
Section 7: Functional Java
-
Section 8: Concurrency
-
Section 9: I/O and NIO
-
Section 10: JVM Internals
-
Section 11: Modern Java Features
-
Section 12: Build Tools and Project Structure
-
Section 13: Testing
-
Section 14: Databases and Persistence
-
Section 15: Networking
-
Section 16: Design and Best Practices
-
Section 17: Reflection and Annotations
-
Section 18: Logging and Diagnostics
-
Section 19: Date, Time, and Internationalization
-
Section 20: Java Platform Module System
-
Section 21: Security in Java
-
Section 22: Advanced Collections and Data Structures
-
Section 23: More Concurrency Patterns
-
Section 24: Compression, Files, and System Integration
-
Section 25: GUI Programming
-
Section 26: Practical Projects
-
Section 27: Data Structures and Algorithms
-
Section 28: Interview and Algorithm Practice
-
Section 29: JSON and Data Interchange
-
Section 30: More Concurrency Utilities
-
Section 31: More Collections and Streams Practice
-
Section 32: More File and System Programming
-
Section 33: Standard Library Deep Dive
-
Section 34: More Practice and Drills
-
Section 35: More Testing and Quality
-
Section 36: More Design Patterns and Architecture
-
Section 37: Career and Ecosystem
-
Section 38: More OOP and Architecture Practice
-
Section 39: More Enterprise Concepts
-
Section 40: Advanced JavaFX
-
Section 41: More Interview Practice
198: Working with Deque as Stack and Queue
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, andpoll()grabs it from the front. Simple and clean.How do I use it as a Stack without getting confused?
To use a
Dequeas 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()andpop()specifically to make theDequeinterface feel like a traditional stack. Under the hood,push()is just a shortcut foraddFirst().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.comOne thing to watch out for:
pop()will throw aNoSuchElementExceptionif the deque is empty. I always suggest checkingisEmpty()first, or usingpollFirst()if you'd rather get anullback 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(), andremoveLast()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
ArrayDequeto 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.
There are no comments for now.