¿Qué es java.util.Stack en Java y cómo funciona?

| Última modificación: 13 de diciembre de 2024 | Tiempo de Lectura: 3 minutos

Algunos de nuestros reconocimientos:

Premios KeepCoding

En algún momento te encontrarás con la necesidad de organizar elementos en un orden específico o de realizar operaciones donde el último elemento agregado sea el primero en salir. Cuando ese momento llegue, debes estar preparado y saber qué hacer. Por supuesto, tendrás que usar java.util.Stack, así que si aún no conoces esta clase y no sabes cómo implementarla, yo te lo explicaré de una forma muy fácil de entender.

java.util.Stack qué es

¿Qué es java.util.Stack?

Quiero explicártelo por medio de una analogía sencilla: Imagina que tienes platos apilados uno sobre otro. Lo único que puedes hacer es quitar el plato que está en la parte superior de la pila de platos o agregar un nuevo plato encima del último que pusiste.

Entonces, java.util.Stack es una clase en Java que modela una pila y te ofrece métodos específicos para trabajar con esta estructura de datos. Como hereda de Vector, también tiene acceso a métodos como add, remove o size y por si fuera poco, incluye operaciones específicas para manejar pilas, como push, pop y peek.

Características de java.util.Stack

  1. Basada en LIFO: El último elemento añadido es el primero en ser retirado. (Como el caso de los platos)
  2. Extiende Vector: Ya te dije que hereda métodos de Vector, de ahí su flexibilidad adicional.
  3. No admite valores nulos: Intentar insertar null puede generar errores.
  4. No es la opción más eficiente: Aunque es funcional, otras alternativas como Deque pueden ser más rápidas en entornos modernos.

Métodos principales de java.util.Stack: Con ejemplos prácticos

Agregar elementos: push()

El método push() añade un elemento al tope de la pila. Recuerda que te servirá para construir la pila.

Ejemplo práctico:

import java.util.Stack;

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

stack.push("Elemento 1");
stack.push("Elemento 2");
stack.push("Elemento 3");

System.out.println("Pila actual: " + stack);
}
}

La salida queda así:

Pila actual: [Elemento 1, Elemento 2, Elemento 3]

Eliminar elementos: pop()

El método pop() elimina y devuelve el elemento en la parte superior de la pila. Ojo aquí, porque si intentas usarlo en una pila vacía, lanzará una excepción.

Ejemplo práctico:

Stack<Integer> stack = new Stack<>();
stack.push(10);
stack.push(20);
stack.push(30);

System.out.println("Elemento eliminado: " + stack.pop());
System.out.println("Pila después del pop: " + stack);

Mira cómo queda la salida:

Elemento eliminado: 30
Pila después del pop: [10, 20]

Consultar el elemento superior: peek()

Algo bueno es que con peek() puedes obtener el elemento en la parte superior de la pila sin eliminarlo.

Ejemplo práctico:

Stack<String> stack = new Stack<>();
stack.push("Java");
stack.push("Python");

System.out.println("Elemento superior: " + stack.peek());

Esta es la salida:

Elemento superior: Python

Verificar si la pila está vacía: empty()

Que no se te olvide que, este método devuelve true si la pila está vacía y false en caso contrario.

Ejemplo práctico:

Stack<Integer> stack = new Stack<>();
System.out.println("¿Pila vacía?: " + stack.empty());

stack.push(1);
System.out.println("¿Pila vacía después de añadir un elemento?: " + stack.empty());

Observa la salida:

¿Pila vacía?: true
¿Pila vacía después de añadir un elemento?: false

Buscar elementos: search()

Este método te ayuda a encontrar la posición de un elemento en la pila. Ten en cuenta que, si el elemento no existe, devuelve -1.

Ejemplo práctico:

Stack<String> stack = new Stack<>();
stack.push("HTML");
stack.push("CSS");
stack.push("JavaScript");

System.out.println("Posición de 'CSS': " + stack.search("CSS"));
System.out.println("Posición de 'Python': " + stack.search("Python"));

La salida sería así:

Posición de 'CSS': 2
Posición de 'Python': -1

Limitaciones de java.util.Stack

Sí, te dije que java.util.Stack te ayudará bastante, pero quiero dejarte claro algunas de sus limitaciones:

  1. Herencia de Vector: Al heredar de Vector, incluye métodos que no siempre son necesarios para trabajar con pilas, lo que puede hacerla menos eficiente.
  2. No es thread-safe: Aunque técnicamente lo es gracias a Vector, su rendimiento no es ideal en aplicaciones multihilo. En estos casos, es mejor usar alternativas como Deque o ConcurrentLinkedDeque.
  3. Reemplazo moderno: Es mejor que uses ArrayDeque en lugar de Stack en aplicaciones modernas, para un mejor rendimiento y flexibilidad.

Creo que ya te quedó claro que la clase java.util.Stack es de las mejores herramientas para entender y trabajar con pilas en Java. Tiene una que otra limitación, pero honestamente te digo que es una excelente opción para aprender y resolver problemas basados en LIFO.

Pon en práctica este conocimiento, ingresando al Bootcamp de Java Full Stack de KeepCoding y transforma tu futuro en la industria tecnológica. En este programa aprenderás a usar estructuras como java.util.Stack y mucho más, preparándote para un sector en constante crecimiento, con alta demanda y salarios competitivos. ¡Es hora de dar el salto a una carrera con estabilidad y proyección!

Ramón Maldonado

Full Stack Developer y Responsable de Formación base en KeepCoding.

Posts más leídos

¡CONVOCATORIA ABIERTA!

Java y Spring Boot

Full Stack Bootcamp

Clases en Directo | Profesores en Activo | Temario 100% actualizado