Guia rápido para Java Stack

Guia rápido para Java Stack

1. Visão geral

Neste artigo, vamos apresentar a classejava.util.Stack e começar a ver como podemos fazer uso dela.

OStack é uma estrutura de dados genérica que representa uma coleção de objetos LIFO (último a entrar, primeiro a sair) permitindo empurrar / estourar elementos em tempo constante.

2. Criação

Vamos começar criando uma instância vazia deStack, usando o construtor padrão, sem argumento:

@Test
public void whenStackIsCreated_thenItHasSize0() {
    Stack intStack = new Stack();

    assertEquals(0, intStack.size());
}

Isso serácreate a Stack with the default capacity of 10. Se o número de elementos adicionados exceder o tamanho total deStack, ele será duplicado automaticamente. No entanto, seu tamanho nunca diminui após a remoção dos elementos.

3. Sincronização

Stack é uma subclasse direta deVector; isso significa quesimilarly to its superclass, it’s asynchronizedimplementation.

No entanto, a sincronização nem sempre é necessária, em tais casos, é aconselhável usarArrayDeque.

4. Adicionando

Vamos começar adicionando um elemento ao topo deStack, com o métodopush() - que também retorna o elemento que foi adicionado:

@Test
public void whenElementIsPushed_thenStackSizeIsIncreased() {
    Stack intStack = new Stack();
    intStack.push(1);

    assertEquals(1, intStack.size());
}

Usar o métodopush() tem o mesmo efeito que usaraddElement(). *T*he only difference is that addElement() returns the result of the operation, instead of the element that was added.

Também podemos adicionar vários elementos ao mesmo tempo:

@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. Recuperando

A seguir, vamos dar uma olhada em como obter e remover o último elemento em umStack:

@Test
public void whenElementIsPoppedFromStack_thenSizeChanges() {
    Stack intStack = new Stack();
    intStack.push(5);
    intStack.pop();

    assertTrue(intStack.isEmpty());
}

Também podemos obter o último elemento de Stack sem removê-lo:

@Test
public void whenElementIsPeeked_thenElementIsNotRemoved() {
    Stack intStack = new Stack();
    intStack.push(5);
    intStack.peek();

    assertEquals(1, intStack.search(5));
    assertEquals(1, intStack.size());
}

6. Procurando um Elemento

Stack nos permite pesquisar um elemento __ e obter sua distância do topo:

@Test
public void whenElementIsOnStack_thenSearchReturnsItsDistanceFromTheTop() {
    Stack intStack = new Stack();
    intStack.push(5);

    assertEquals(1, intStack.search(5));
}

O resultado é um índice deObject fornecido. Se mais de umObject estiver presente, o índice deObject mais próximo do topo será retornado. O item que está no topo da pilha é considerado na posição 1.

SeObject não for encontrado,search() retornará -1.

6.2. Obtendo Índice de Elemento

Para obter um índice de um elemento em Stack,, também podemos usar os métodosindexOf()elastIndexOf():

@Test
public void whenElementIsOnStack_thenIndexOfReturnsItsIndex() {
    Stack intStack = new Stack();
    intStack.push(5);
    int indexOf = intStack.indexOf(5);

    assertEquals(0, indexOf);
}

OlastIndexOf() sempre encontrará o índice do elemento que está mais próximo do topo da pilha. Isso funciona de forma muito semelhante asearch() - com a importante diferença deit returns the index, em vez da distância do topo:

@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. Removendo elementos

Além da operaçãopop(), usada para remover e recuperar elementos, também podemos usar várias operações herdadas da classeVector para remover elementos.

7.1. Removendo Elementos Especificados

Podemos usar o métodoremoveElement() para remover a primeira ocorrência de determinado elemento:

@Test
public void whenRemoveElementIsInvoked_thenElementIsRemoved() {
    Stack intStack = new Stack();
    intStack.push(5);
    intStack.push(5);
    intStack.removeElement(5);

    assertEquals(1, intStack.size());
}

Também podemos usarremoveElementAt() para excluir elementos em um índice especificado emStack:

@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. Removendo vários elementos

Vamos dar uma olhada rápida em como remover vários elementos deStack usando a APIremoveAll() - que pegaráCollection como argumento e removerá todos os elementos correspondentes deStack:

@Test
public void 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());
}

Também é possível remover todos os elementos deStack usando os métodosclear() ouremoveAllElements(); ambos os métodos funcionam da mesma forma:

@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());
}

7.3. Removendo Elementos Usando Filtro

Também podemos usar uma condição para remover elementos deStack.. Vamos ver como fazer isso usandoremoveIf(), com uma expressão 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. Iterando

Stack nos permite usar tanto umIteratore umListIterator. A principal diferença é que o primeiro nos permite atravessarStack em uma direção e o segundo permite fazer isso em ambas direcoes:

@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));
}

Todos osIterators retornados porStack são fail-fast.

9. API Stream

A Stack é uma coleção, o que significa que podemos usá-lo com Java 8Streams API. Using Streams 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);
    int[] intArray = intStack.stream()
      .mapToInt(element -> (int)element)
      .filter(element -> element <= 3)
      .toArray();

    assertEquals(3, intArray.length);
}

10. Sumário

Este tutorial foi um guia rápido para entender o JavaStack. Para saber mais sobre este tópico, consulteJavadoc.

E, como sempre, todos os exemplos de código podem ser encontradosover on Github.