Stacks are essential data structures in programming that follow the Last-In, First-Out (LIFO) principle, meaning that the last item added to the stack is the first one removed. Stacks are useful for managing data efficiently, such as reversing a word, evaluating expressions, or implementing undo/redo operations. In this blog post, you will learn how to implement stacks in Java using different built-in classes, such as Stack, LinkedList and Deque. You will also learn how to create a Maven project to develop and test your stack implementation using JUnit and AssertJ.
- Prerequisites
- Creating a Maven Project
- Implementing Stack and Deque in Java
- Running the Test
- Conclusion
Prerequisites
If you don’t already have Maven installed, you can download it from the official Maven website https://maven.apache.org/download.cgi or through SDKMAN https://sdkman.io/sdks#maven
You can clone the https://github.com/dmakariev/examples
repository.
git clone https://github.com/dmakariev/examples.git
cd examples/java-core/stack-deque
Creating a Maven Project
Let’s create a our project
- Open your terminal and navigate to the directory where you want to create your project.
- Run the following command to generate a new Maven project:
mvn archetype:generate -DgroupId=com.makariev.examples.core -DartifactId=stack-deque -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
This command generates a basic Maven project structure with a sample Java class, and the group ID and artifact ID are set as per your requirements.
Deleting Initial Files and Updating Dependencies
To clean up the initial files generated by the Maven archetype and update dependencies, follow these steps:
- Delete the
src/main/java/com/makariev/examples/core/App.java
file. - Delete the
src/test/java/com/makariev/examples/core/AppTest.java
file. - Open the
pom.xml
file and delete the JUnit 3 dependency (junit:junit). - Add the JUnit 5 and AssertJ dependencies to the
pom.xml
file:
<dependencies>
<!-- JUnit 5 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.10.0</version> <!-- Use the latest version -->
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.10.0</version> <!-- Use the latest version -->
<scope>test</scope>
</dependency>
<!-- AssertJ -->
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.24.2</version> <!-- Use the latest version -->
<scope>test</scope>
</dependency>
</dependencies>
Implementing Stack and Deque in Java
Now, let’s create a simple Java program that demonstrates the use of both stacks and deques.
Stack and Deque Example
Create a new Java class, StackDequeExampleTest.java
, in the src/test/java/com/makariev/examples/core
directory with the following content:
package com.makariev.examples.core;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.LinkedList;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Stack;
public class StackDequeExampleTest {
@Test
void testStackLinkedListDeque() {
// Create a stack
final Stack<String> stack = new Stack<>();
stack.push("Alan Turing");
stack.push("Grace Hopper");
stack.push("Linus Torvalds");
stack.push("Ada Lovelace");
stack.push("Donald Knuth");
// Check the size of the stack
assertThat(stack.size()).isEqualTo(5);
// Pop elements from the stack and check their order (FILO)
assertThat(stack.pop()).isEqualTo("Donald Knuth");
assertThat(stack.pop()).isEqualTo("Ada Lovelace");
assertThat(stack.pop()).isEqualTo("Linus Torvalds");
assertThat(stack.pop()).isEqualTo("Grace Hopper");
assertThat(stack.pop()).isEqualTo("Alan Turing");
// Create a LinkedList (used as a stack)
final LinkedList<String> linkedList = new LinkedList<>();
linkedList.push("Alan Turing");
linkedList.push("Grace Hopper");
linkedList.push("Linus Torvalds");
linkedList.push("Ada Lovelace");
linkedList.push("Donald Knuth");
// Check the size of the linked list (stack)
assertThat(linkedList.size()).isEqualTo(5);
// Remove elements from the linked list (stack) and check their order (FILO)
assertThat(linkedList.pop()).isEqualTo("Donald Knuth");
assertThat(linkedList.pop()).isEqualTo("Ada Lovelace");
assertThat(linkedList.pop()).isEqualTo("Linus Torvalds");
assertThat(linkedList.pop()).isEqualTo("Grace Hopper");
assertThat(linkedList.pop()).isEqualTo("Alan Turing");
// Create a Deque (used as a stack)
final Deque<String> deque = new ArrayDeque<>();
deque.push("Alan Turing");
deque.push("Grace Hopper");
deque.push("Linus Torvalds");
deque.push("Ada Lovelace");
deque.push("Donald Knuth");
// Check the size of the deque (stack)
assertThat(deque.size()).isEqualTo(5);
// Remove elements from the deque (stack) and check their order (FILO)
assertThat(deque.pop()).isEqualTo("Donald Knuth");
assertThat(deque.pop()).isEqualTo("Ada Lovelace");
assertThat(deque.pop()).isEqualTo("Linus Torvalds");
assertThat(deque.pop()).isEqualTo("Grace Hopper");
assertThat(deque.pop()).isEqualTo("Alan Turing");
}
}
In this single JUnit 5 test, we demonstrate the use of both stacks and deques. We push the names of famous computer scientists onto the data structures, check the size, and then pop the names to demonstrate that they come out in reverse order.
Running the Test
To run the test, execute the following command in the project’s root directory:
mvn test
JUnit 5 and AssertJ will execute the test, and you should see output indicating whether the test passed or failed.
Conclusion
In this blog post, we’ve explored the concept of stack and deque data structures in Java. Stacks and deques are essential data structures for various programming scenarios, and mastering them is vital for any Java developer.
Happy coding!