Краткое руководство по стеку Java

Краткое руководство по стеку Java

1. обзор

В этой статье мы познакомим вас с классомjava.util.Stack и начнем искать способы его использования.

Stack - это общая структура данных, которая представляет коллекцию объектов LIFO (последний вошел - первым ушел), позволяющую выталкивать / выталкивать элементы в постоянное время.

2. Творчество

Начнем с создания пустого экземпляраStack, используя конструктор по умолчанию без аргументов:

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

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

Это будетcreate a Stack with the default capacity of 10.. Если количество добавленных элементов превышает общий размерStack, оно будет автоматически удвоено. Однако его размер никогда не уменьшится после удаления элементов.

3. синхронизация

Stack является прямым подклассомVector; это означает, чтоsimilarly to its superclass, it’s asynchronizedimplementation.

Однако синхронизация требуется не всегда, в таких случаях рекомендуется использоватьArrayDeque.

4. Добавление

Начнем с добавления элемента в началоStack с помощью методаpush(), который также возвращает добавленный элемент:

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

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

Использование методаpush() имеет тот же эффект, что и использованиеaddElement(). *T*he only difference is that addElement() returns the result of the operation, instead of the element that was added.

Мы также можем добавить несколько элементов одновременно:

@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. Получение

Затем давайте посмотрим, как получить и удалить последний элемент вStack:

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

    assertTrue(intStack.isEmpty());
}

Мы также можем получить последний элемент Stack, не удаляя его:

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

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

6. Поиск элемента

Stack позволяет нам искать элемент __ и определять расстояние до него сверху:

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

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

Результат - индекс заданногоObject. Если присутствует более одногоObject, возвращается индексObject, ближайшего к вершине. Элемент, находящийся на вершине стека, считается находящимся в позиции 1.

ЕслиObject не найден,search() вернет -1.

6.2. Получение индекса элемента

Чтобы получить индекс элемента в Stack,, мы также можем использовать методыindexOf() иlastIndexOf():

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

    assertEquals(0, indexOf);
}

lastIndexOf() всегда найдет индекс элемента, ближайшего к вершине стека. Это работает очень похоже наsearch() - с той важной разницей, чтоit returns the index вместо расстояния от вершины:

@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. Удаление элементов

Помимо операцииpop(), используемой как для удаления, так и для извлечения элементов, мы также можем использовать несколько операций, унаследованных от классаVector, для удаления элементов.

7.1. Удаление указанных элементов

Мы можем использовать методremoveElement(), чтобы удалить первое вхождение данного элемента:

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

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

Мы также можем использоватьremoveElementAt() для удаления элементов под указанным индексом вStack:

@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. Удаление нескольких элементов

Давайте быстро рассмотрим, как удалить несколько элементов изStack с помощью APIremoveAll(), который будет приниматьCollection в качестве аргумента и удалять все совпадающие элементы изStack:

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

Также возможно удалить все элементы изStack с помощью методовclear() илиremoveAllElements(); оба этих метода работают одинаково:

@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. Удаление элементов с помощью фильтра

Мы также можем использовать условие для удаления элементов изStack.. Давайте посмотрим, как это сделать, используяremoveIf() с выражением фильтра в качестве аргумента:

@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. Итерация

Stack позволяет нам использовать какIterator, так иListIterator.. Основное различие состоит в том, что первый позволяет нам перемещатьStack в одном направлении, а второй позволяет делать это в в обоих направлениях:

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

ВсеIterators, возвращаемыеStack, работают без сбоев.

9. Stream API

A Stack - это коллекция, что означает, что мы можем использовать ее с 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. Резюме

Это руководство было кратким руководством по пониманию JavaStack. Чтобы узнать больше об этой теме, обратитесь кJavadoc.

И, как всегда, можно найти все образцы кодаover on Github.