我需要一个堆栈数据结构为我的用例。我应该能够将项目推入数据结构,我只想从堆栈中检索最后一项。JavaDoc for Stack说:

一个更完整和一致的后进先出堆栈操作集是 由Deque接口及其实现提供,这应该 优先用于该类。例如:

Deque<Integer> stack = new ArrayDeque<>();

我肯定不希望在这里使用同步行为,因为我将在方法的本地使用这个数据结构。除此之外,为什么我更喜欢Deque而不是Stack呢?

附:Deque的javadoc说:

Deques也可以用作后进先出(LIFO)堆栈。这 接口应该优先于遗留的Stack类。


当前回答

对我来说,这一点是缺失的: Stack是线程安全的,因为它是从Vector派生的,而大多数deque实现不是,因此如果你只在单个线程中使用它,速度会更快。

其他回答

Deque在实现方面优于stack有以下几个原因:

Deque is an interface and stack is a class: In class creation it is better to implement an interface than extend a class because after extending you cannot extend another class, you can only implement an interface in the other hand when you implement an interface you can extend a class and also implement another interfaces. Synchronization: Because stack class is a subclass of the vector class which is asynchronized therefor stack is too But Deque is not. So if there is no need for synchronization then for better performance we should use Deque. Deque‘s iterator works the way we expect for a stack: iteration in a stack is bottom to top (FIFO (First In First Out)). But iteration in a Deque is top to bottom (LIFO (Last In First Out)). Stack isn't truly LIFO: We know that stack is a subclass of the vector class so we can access to elements by their indexes which is against LIFO contract.

如果出于某种原因你想从Stack转换到Deque,但想在转换到ArrayList时保持相同的顺序,你可以使用Deque. descent iterator()。

但是ArrayList没有接受Iterator的构造函数,所以你可能想把它和一个库结合起来,比如Guava(或Apache Commons):

Lists.newArrayList(deque.descendingIterator()) // Guava

或者Java 8:

List<Integer> list = new ArrayList<>();
deque.descendingIterator().forEachRemaining(list::add);

一方面,它在继承方面更合理。在我看来,Stack扩展Vector的事实真的很奇怪。在Java早期,继承被过度使用IMO—属性是另一个例子。

对我来说,你引用的文件中的关键字是一致的。Deque公开了一组操作,这些操作都是关于从集合的开头或结尾获取/添加/删除项,迭代等等——仅此而已。故意没有办法通过位置访问元素,Stack公开了这一点,因为它是Vector的子类。

哦,Stack也没有接口,所以如果你知道你需要Stack操作,你最终会提交到一个特定的具体类,这通常不是一个好主意。

正如评论中指出的那样,Stack和Deque的迭代顺序是反向的:

Stack<Integer> stack = new Stack<>();
stack.push(1);
stack.push(2);
stack.push(3);
System.out.println(new ArrayList<>(stack)); // prints 1, 2, 3


Deque<Integer> deque = new ArrayDeque<>();
deque.push(1);
deque.push(2);
deque.push(3);
System.out.println(new ArrayList<>(deque)); // prints 3, 2, 1

这在JavaDocs for Deque.iterator()中也有解释:

以适当的顺序返回该deque中元素的迭代器。元素将按照从第一个(头)到最后一个(尾)的顺序返回。

使用Deque而不是Stack的另一个原因是Deque有能力使用流转换为列表,同时保持LIFO概念的应用,而Stack没有。

Stack<Integer> stack = new Stack<>();
Deque<Integer> deque = new ArrayDeque<>();

stack.push(1);//1 is the top
deque.push(1)//1 is the top
stack.push(2);//2 is the top
deque.push(2);//2 is the top

List<Integer> list1 = stack.stream().collect(Collectors.toList());//[1,2]

List<Integer> list2 = deque.stream().collect(Collectors.toList());//[2,1]

业绩可能是原因之一。我使用的一种算法通过将Stack替换为Deque将时间从7.6分钟缩短到1.5分钟。