Есть ли ошибка в java.util.Stack Iterator?
Сегодня я пытался вставить класс java.util.Stack
, а затем использовать Iterator
для итерации (без использования pop) через элементы. Я ожидал собственности LIFO, но удивился.
Вот код, который я пытался.
import java.util.*;
import java.util.Stack;
public class Main {
public static void main(String[] args) {
RobStack<Integer> rstack = new RobStack<Integer>(); // Correct Implementation
Stack<Integer> jstack = new Stack<Integer>(); // Default Java Implementation
rstack.push(0); jstack.push(0);
rstack.push(1); jstack.push(1);
rstack.push(2); jstack.push(2);
rstack.push(3); jstack.push(3);
System.out.print("Algo Stack: ");
for (int i : rstack)
System.out.print(i + " ");
System.out.print("\nJava Stack: ");
for (int i : jstack)
System.out.print(i + " ");
}
}
Вывод указанной выше программы приведен ниже:
Algo Stack: 3 2 1 0
Java Stack: 0 1 2 3
В приведенном выше коде jstack
используется реализация Java по умолчанию, а rstack
использует реализацию предоставленную Робертом Седжуиком для его класса алгоритмов. Я обнаружил, что реализация Роберта Роберта работает нормально, но реализация java.util.Stack
не выполняется.
Является ли это ошибкой или это дизайн?
Ответы
Ответ 1
Смотрите Идентификатор ошибки 4475301: RFE: java.util.Stack.iterator() выполняет итерацию неправильным образом. Это поведение (плохой) дизайн. Встроенные Java Stack
методы итератора наследуются от других классов, поэтому они не ведут себя так, как вы ожидали.
Ответ 2
Вы должны использовать Deque вместо Stack.
Deque<Integer> stack = new ArrayDeque<Integer>();
См. Oracle Doc
Ответ 3
Ну, в принципе, вы не должны перебирать Stack
, а только нажимать сверху или всплывать сверху. Что касается реальной реализации, большинство языков, включая Java, используют другой collection type
для реализации Stack
. С точки зрения строгих требований, она должна обеспечивать постоянное время push, top and pop
.
Любые дополнительные функции (или ошибка в этом случае) должны просто игнорироваться и не использоваться для кодирования.
Ответ 4
Возможно, вы можете использовать .get() для печати элементов внутри стека сверху вниз.
Stack<Integer> stack = new Stack<Integer>();
stack.push(3);
stack.push(2);
stack.push(1);
// print from top to bottom
for(int i = stack.size() - 1; i >= 0; i--){
System.out.println(stack.get(i));
}
/*
output
1
2
3
*/
Ответ 5
Коллекции Eclipse включает в себя изменчивую реализацию стека где итератор возвращает значения сверху вниз. Этот код печатает 3, 2, затем 1.
MutableStack<Integer> stack = ArrayStack.newStack();
stack.push(1);
stack.push(2);
stack.push(3);
for (Iterator<Integer> iterator = stack.iterator(); iterator.hasNext(); )
{
Integer each = iterator.next();
System.out.println(each);
}
MutableStack
не расширяет MutableCollection
или Collection
, так что вы не можете удалить из середины стека, например. Методы, которые реализуют внутренние итерационные шаблоны, такие как forEach()
, select()
, collect()
, anySatisfy()
, allSatisfy()
и т.д., Также обрабатывают элементы сверху донизу. Этот код печатает то же самое.
stack.forEach(Procedures.println(System.out));
Примечание. Я являюсь коммиттером для коллекций Eclipse.
Ответ 6
Stack наследует .listIterator() от AbstractList, который допускает итерацию обратного порядка.
Stack<Integer> stack = new Stack<Integer>();
stack.push(1);
stack.push(2);
stack.push(3);
for (ListIterator<Integer> iterator = stack.listIterator(stack.size()); iterator.hasPrevious();) {
Integer integer = iterator.previous();
System.out.println(integer);
}
// Output: 3 2 1