1. Información general
En este artículo rápido, presentaremos la clase java.util.Stack y comenzaremos a ver cómo podemos hacer uso de ella.
Stack es una estructura de datos genérica que representa una colección de objetos LIFO (último en entrar, primero en salir) que permite empujar / hacer estallar elementos en tiempo constante.
Para las nuevas implementaciones, deberíamos preferir una interfaz Deque y sus implementaciones . Deque define un conjunto más completo y coherente de operaciones LIFO. Sin embargo, es posible que debamos tratar con la clase Stack , especialmente en el código heredado, ¿es importante conocerlo mejor?
2. Crea una pila
Comencemos por crear una instancia vacía de Stack , usando el constructor sin argumentos predeterminado:
@Test public void whenStackIsCreated_thenItHasSizeZero() { Stack intStack = new Stack(); assertEquals(0, intStack.size()); }
Esto creará una pila con la capacidad predeterminada de 10. Si el número de elementos agregados excede el tamaño total de la pila , se duplicará automáticamente. Sin embargo, su tamaño nunca se reducirá después de eliminar elementos.
3. Sincronización para la pila
Stack es una subclase directa de Vector ; esto significa que, al igual que su superclase, es una implementación sincronizada .
Sin embargo, la sincronización no siempre es necesaria; en tales casos, se recomienda utilizar ArrayDeque .
4. Agregar a una pila
Comencemos agregando un elemento en la parte superior de la pila , con el método push () , que también devuelve el elemento que se agregó:
@Test public void whenElementIsPushed_thenStackSizeIsIncreased() { Stack intStack = new Stack(); intStack.push(1); assertEquals(1, intStack.size()); }
Usar el método push () tiene el mismo efecto que usar addElement (). La única diferencia es que addElement () devuelve el resultado de la operación, en lugar del elemento que se agregó.
También podemos agregar varios elementos a la vez:
@Test public void whenMultipleElementsArePushed_thenStackSizeIsIncreased() { Stack intStack = new Stack(); List intList = Arrays.asList(1, 2, 3, 4, 5, 6, 7); boolean result = intStack.addAll(intList); assertTrue(result); assertEquals(7, intList.size()); }
5. Recuperar de una pila
A continuación, echemos un vistazo a cómo obtener y eliminar el último elemento de una pila :
@Test public void whenElementIsPoppedFromStack_thenElementIsRemovedAndSizeChanges() { Stack intStack = new Stack(); intStack.push(5); Integer element = intStack.pop(); assertEquals(Integer.valueOf(5), element); assertTrue(intStack.isEmpty()); }
También podemos obtener el último elemento de la tachuela S sin quitarlo:
@Test public void whenElementIsPeeked_thenElementIsNotRemovedAndSizeDoesNotChange() { Stack intStack = new Stack(); intStack.push(5); Integer element = intStack.peek(); assertEquals(Integer.valueOf(5), element); assertEquals(1, intStack.search(5)); assertEquals(1, intStack.size()); }
6. Busque un elemento en una pila
6.1. Buscar
Stack nos permite buscar un elementoy obtenga su distancia desde la parte superior:
@Test public void whenElementIsOnStack_thenSearchReturnsItsDistanceFromTheTop() { Stack intStack = new Stack(); intStack.push(5); intStack.push(8); assertEquals(2, intStack.search(5)); }
El resultado es un índice de un objeto dado. Si hay más de un elemento presente, el índice de unomás cercano a la parte superior se devuelve . El artículo que está en la parte superior de la pila se considera en la posición 1.
Si no se encuentra el objeto, search () devolverá -1.
6.2. Obtener índice de elemento
Para obtener un índice de un elemento en la tachuela S , también podemos usar los métodos indexOf () y lastIndexOf () :
@Test public void whenElementIsOnStack_thenIndexOfReturnsItsIndex() { Stack intStack = new Stack(); intStack.push(5); int indexOf = intStack.indexOf(5); assertEquals(0, indexOf); }
El lastIndexOf () siempre encontrará el índice del elemento que está más cerca de la parte superior de la pila . Esto funciona de manera muy similar a search () , con la importante diferencia de que devuelve el índice, en lugar de la distancia desde la parte superior:
@Test public void whenMultipleElementsAreOnStack_thenIndexOfReturnsLastElementIndex() { Stack intStack = new Stack(); intStack.push(5); intStack.push(5); intStack.push(5); int lastIndexOf = intStack.lastIndexOf(5); assertEquals(2, lastIndexOf); }
7. Quitar elementos de una pila
Aparte de la operación pop () , que se usa tanto para eliminar como para recuperar elementos, también podemos usar múltiples operaciones heredadas de la clase Vector para eliminar elementos.
7.1. Eliminar elementos especificados
Podemos usar el método removeElement () para eliminar la primera aparición del elemento dado:
@Test public void whenRemoveElementIsInvoked_thenElementIsRemoved() { Stack intStack = new Stack(); intStack.push(5); intStack.push(5); intStack.removeElement(5); assertEquals(1, intStack.size()); }
También podemos usar removeElementAt () para eliminar elementos bajo un índice específico en la Pila:
@Test public void whenRemoveElementAtIsInvoked_thenElementIsRemoved() { Stack intStack = new Stack(); intStack.push(5); intStack.push(7); intStack.removeElementAt(1); assertEquals(-1, intStack.search(7)); }
7.2. Eliminar varios elementos
Echemos un vistazo rápido a cómo eliminar varios elementos de una pila utilizando la API removeAll () , que tomará una colección como argumento y eliminará todos los elementos coincidentes de la pila :
@Test public void givenElementsOnStack_whenRemoveAllIsInvoked_thenAllElementsFromCollectionAreRemoved() { Stack intStack = new Stack(); List intList = Arrays.asList(1, 2, 3, 4, 5, 6, 7); intStack.addAll(intList); intStack.add(500); intStack.removeAll(intList); assertEquals(1, intStack.size()); assertEquals(1, intStack.search(500)); }
También es posible eliminar todos los elementos de la pila usando los métodos clear () o removeAllElements () ; ambos métodos funcionan igual:
@Test public void whenRemoveAllElementsIsInvoked_thenAllElementsAreRemoved() { Stack intStack = new Stack(); intStack.push(5); intStack.push(7); intStack.removeAllElements(); assertTrue(intStack.isEmpty()); }
7.3. Eliminar elementos mediante el filtro
También podemos usar una condición para eliminar elementos de la pila. Veamos cómo hacer esto usando removeIf () , con una expresión de filtro como argumento:
@Test public void whenRemoveIfIsInvoked_thenAllElementsSatysfyingConditionAreRemoved() { Stack intStack = new Stack(); List intList = Arrays.asList(1, 2, 3, 4, 5, 6, 7); intStack.addAll(intList); intStack.removeIf(element -> element < 6); assertEquals(2, intStack.size()); }
8. Iterar sobre una pila
Stack allows us to use both an Iterator and a ListIterator. The main difference is that the first one allows us to traverse Stack in one direction and second allows us to do this in both directions:
@Test public void whenAnotherStackCreatedWhileTraversingStack_thenStacksAreEqual() { Stack intStack = new Stack(); List intList = Arrays.asList(1, 2, 3, 4, 5, 6, 7); intStack.addAll(intList); ListIterator it = intStack.listIterator(); Stack result = new Stack(); while(it.hasNext()) { result.push(it.next()); } assertThat(result, equalTo(intStack)); }
All Iterators returned by Stack are fail-fast.
9. Stream API for the Java Stack
Stack is a collection, which means we can use it with Java 8 Streams API. Using Stream with the Stack is similar to using it with any other Collection:
@Test public void whenStackIsFiltered_allElementsNotSatisfyingFilterConditionAreDiscarded() { Stack intStack = new Stack(); List inputIntList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 9, 10); intStack.addAll(inputIntList); List filtered = intStack .stream() .filter(element -> element <= 3) .collect(Collectors.toList()); assertEquals(3, filtered.size()); }
10. Summary
This tutorial is a quick and practical guide to understand this core class in Java – the Stack.
Por supuesto, puede explorar la API completa en Javadoc.
Y, como siempre, todas las muestras de código se pueden encontrar en GitHub.