The Stack class in Java is found in the java.util package and it is a subclass of Vector and implements the Last-In-First-Out (LIFO) data structure. This means the last element added to the stack is the first one to be removed.

The Stack class extends Vector which implements the List interface. A Vector is a re-sizable collection. It grows its size to accommodate new elements and shrinks the size when the elements are removed. Since the Stack class extends Vector, it also grows and shrinks its size as needed when new elements are added or removed.

Basic Operations on a Stack

import java.util.Stack;

public class StackOperations {
    public static void main(String[] args) {
        // 1. Creating a Stack
        Stack<Integer> stack = new Stack<>();

        // 2. Pushing elements onto the Stack
        stack.push(10);
        stack.push(20);
        stack.push(30);
        stack.push(40);
        System.out.println("Stack after pushing 10, 20, 30, 40: " + stack);

        // 3. Popping an element from the Stack
        int popped = stack.pop();
        System.out.println("Popped element: " + popped);

        // 4. Peeking (looking at the top without popping)
        int top = stack.peek();
        System.out.println("Element on top: " + top);

        // 5. Checking if the Stack is empty
        boolean isEmpty = stack.isEmpty();
        System.out.println("Is the stack empty? " + isEmpty);

        // 6. Finding the position of an element
        int position = stack.search(20);
        System.out.println("Position of 20 in the stack: " + position);
    }
}

Output:

Stack after pushing 10, 20, 30, 40: [10, 20, 30, 40]
Popped element: 40
Element on top: 30
Is the stack empty? false
Position of 20 in the stack: 2

Explanation:

1. A Stack of type Integer is created.

2. Four integers (10, 20, 30, and 40) are pushed onto the stack.

3. The pop() method is used to remove the top element of the stack.

4. The peek() method is used to view the top element without removing it.

5. The isEmpty() method is used to check if the stack is empty.

6. The search() method is used to find the position of an element in the stack. The position is 1-based, with the topmost position being 1.

Iterating Over a Stack in Various Ways

import java.util.Stack;
import java.util.Iterator;

public class StackIteration {
    public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();

        // Populate the stack
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);

        // 1. Using Java 8 forEach()
        System.out.println("Using Java 8 forEach():");
        stack.forEach(num -> System.out.print(num + " "));
        System.out.println();

        // 2. Using iterator()
        System.out.println("Using iterator():");
        Iterator<Integer> iterator = stack.iterator();
        while(iterator.hasNext()) {
            System.out.print(iterator.next() + " ");
        }
        System.out.println();

        // 3. Using iterator() with forEachRemaining()
        System.out.println("Using iterator() with forEachRemaining():");
        iterator = stack.iterator();
        iterator.forEachRemaining(num -> System.out.print(num + " "));
        System.out.println();

        // 4. Using listIterator() to iterate from top to bottom
        System.out.println("Using listIterator() from top to bottom:");
        for(int i = stack.size() - 1; i >= 0; i--) {
            System.out.print(stack.get(i) + " ");
        }
    }
}

Output:

Using Java 8 forEach():
1 2 3 4
Using iterator():
1 2 3 4
Using iterator() with forEachRemaining():
1 2 3 4
Using listIterator() from top to bottom:
4 3 2 1

Explanation:

1. The stack is populated with numbers from 1 to 4.

2. The Java 8 forEach() method is used to iterate over the stack and print each number.

3. An iterator is used to traverse the stack in its natural order.

4. The iterator is used again with the forEachRemaining() method, which is a Java 8 feature, to print each number.

5. The listIterator() method along with the stack's size is used to iterate from the top to the bottom of the stack.

Real-World Example: Web Browser Navigation

A very intuitive use case for Stack is in web browser navigation for the “Back” and “Forward” functionality. When a user visits a series of web pages, the URLs can be pushed onto a stack. When the user hits the “Back” button, the browser can pop the URLs from the stack to go back to the previous page.

Step 1: Define the Browser class.

public class Browser {
    private Stack<String> backStack = new Stack<>();
    private Stack<String> forwardStack = new Stack<>();

    // Visit a new page.
    public void visit(String url) {
        System.out.println("Visiting: " + url);
        backStack.push(url);
        forwardStack.clear();  // Clear forward stack upon visiting a new URL
    }

    // Navigate back.
    public void goBack() {
        if (backStack.size() > 1) {  // Keep at least one URL in backStack to display current page
            forwardStack.push(backStack.pop());
            System.out.println("Going back to: " + backStack.peek());
        } else {
            System.out.println("Cannot go back further.");
        }
    }

    // Navigate forward.
    public void goForward() {
        if (!forwardStack.isEmpty()) {
            backStack.push(forwardStack.pop());
            System.out.println("Going forward to: " + backStack.peek());
        } else {
            System.out.println("Cannot go forward.");
        }
    }
}

Step 2: Use the Browser.

public static void main(String[] args) {
    Browser browser = new Browser();

    browser.visit("google.com");
    browser.visit("example.com");
    browser.visit("openai.com");

    browser.goBack();    // Output: Going back to: example.com
    browser.goBack();    // Output: Going back to: google.com
    browser.goForward(); // Output: Going forward to: example.com
}

This example demonstrates the power of Stack in modeling problems where the Last-In-First-Out principle is evident.

Conclusion

In this tutorial, you learned what is a Stack, how to create a Stack in Java, how to perform push and pop operations in a Stack, how to check if the Stack is empty, how to find the size of the Stack, how to search for an element in the Stack, how to iterate over a Stack, and a simple real-world example.