Stack

Stack — класс из пакета java.util, реализующий классический стек LIFO («последним пришёл — первым вышел»). Унаследован от Vector, поэтому помимо стековых методов поддерживает все методы списка.

В современном Java-коде вместо Stack чаще используют Deque<E> (например, ArrayDeque) — он не синхронизирован и быстрее. Тем не менее Stack остаётся в стандартной библиотеке и часто встречается в учебных задачах и в существующем коде.

Зачем нужен

  • Хранение истории действий с поддержкой «отмены» (undo).

  • Обход деревьев и графов в глубину (DFS).

  • Разбор скобок, инфиксных и постфиксных выражений.

  • Любая логика, где важна именно LIFO-семантика.

Конструкторы

  • Stack() — пустой стек.

Популярные методы

  • push(E item) — положить элемент на вершину.

  • pop() — снять и вернуть верхний элемент; бросает EmptyStackException если стек пуст.

  • peek() — посмотреть верхний элемент, не снимая; то же исключение, если пусто.

  • empty()true если стек пуст.

  • search(Object o) — позиция элемента от вершины (1 = на вершине), -1 если нет.

  • size() — текущий размер.

Пример 1. Базовые операции

import java.util.Stack;

public class Basics {
    public static void main(String[] args) {
        Stack<String> stack = new Stack<>();
        stack.push("A");
        stack.push("B");
        stack.push("C");

        System.out.println("Вершина: " + stack.peek());
        System.out.println("Снимаем: " + stack.pop());
        System.out.println("Стек: " + stack);
    }
}

Вывод:

Вершина: C
Снимаем: C
Стек: [A, B]

Пример 2. Опустошение стека

import java.util.Stack;

public class DrainStack {
    public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        for (int i = 1; i <= 4; i++) stack.push(i);

        while (!stack.empty()) {
            System.out.print(stack.pop() + " ");
        }
        System.out.println();
    }
}

Вывод:

4 3 2 1

Пример 3. Реверс строки

import java.util.Stack;

public class ReverseString {
    public static void main(String[] args) {
        String input = "AlashEd";
        Stack<Character> stack = new Stack<>();
        for (char c : input.toCharArray()) stack.push(c);

        StringBuilder sb = new StringBuilder();
        while (!stack.empty()) sb.append(stack.pop());
        System.out.println(sb);
    }
}

Вывод:

dEhsalA

Пример 4. Проверка сбалансированности скобок

import java.util.Stack;

public class Brackets {
    public static boolean isBalanced(String s) {
        Stack<Character> stack = new Stack<>();
        for (char c : s.toCharArray()) {
            if (c == '(' || c == '[' || c == '{') stack.push(c);
            else if (c == ')' || c == ']' || c == '}') {
                if (stack.empty()) return false;
                char open = stack.pop();
                if (open == '(' && c != ')') return false;
                if (open == '[' && c != ']') return false;
                if (open == '{' && c != '}') return false;
            }
        }
        return stack.empty();
    }

    public static void main(String[] args) {
        System.out.println(isBalanced("(a+b)*[c-d]"));
        System.out.println(isBalanced("(a+b]"));
        System.out.println(isBalanced("{[()]}"));
    }
}

Вывод:

true
false
true

Пример 5. Поиск позиции элемента

import java.util.Stack;

public class SearchPos {
    public static void main(String[] args) {
        Stack<String> stack = new Stack<>();
        stack.push("Arduino");
        stack.push("ESP32");
        stack.push("RPi");

        System.out.println("RPi:     " + stack.search("RPi"));
        System.out.println("ESP32:   " + stack.search("ESP32"));
        System.out.println("Arduino: " + stack.search("Arduino"));
        System.out.println("Linux:   " + stack.search("Linux"));
    }
}

Вывод:

RPi:     1
ESP32:   2
Arduino: 3
Linux:   -1

Пример 6. Undo-история

import java.util.Stack;

public class UndoHistory {
    public static void main(String[] args) {
        Stack<String> history = new Stack<>();
        history.push("draw_line");
        history.push("draw_circle");
        history.push("fill_red");

        System.out.println("Undo: " + history.pop());
        System.out.println("Undo: " + history.pop());
        System.out.println("Осталось: " + history);
    }
}

Вывод:

Undo: fill_red
Undo: draw_circle
Осталось: [draw_line]

Пример 7. EmptyStackException

import java.util.Stack;

public class EmptyDemo {
    public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        try {
            stack.pop();
        } catch (Exception e) {
            System.out.println("Поймали: " + e.getClass().getSimpleName());
        }
    }
}

Вывод:

Поймали: EmptyStackException

Пример 8. Постфиксный калькулятор

import java.util.Stack;

public class Postfix {
    public static int compute(String expr) {
        Stack<Integer> st = new Stack<>();
        for (String tok : expr.split(" ")) {
            switch (tok) {
                case "+": st.push(st.pop() + st.pop()); break;
                case "*": st.push(st.pop() * st.pop()); break;
                case "-": { int b = st.pop(); int a = st.pop(); st.push(a - b); break; }
                default:  st.push(Integer.parseInt(tok));
            }
        }
        return st.pop();
    }

    public static void main(String[] args) {
        System.out.println(compute("3 4 + 2 *"));
        System.out.println(compute("5 1 2 + 4 * + 3 -"));
    }
}

Вывод:

14
14

См. также

Примечание

Описание основано на официальной документации Oracle Java SE 21 API (https://docs.oracle.com/en/java/javase/21/docs/api/). Материал распространяется на условиях Oracle Free Documentation License. Тексты статьи написаны редакцией AlashEd своими словами; примеры кода — авторские.