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

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

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

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

附:Deque的javadoc说:

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


当前回答

使用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,但想在转换到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类描述中提到的不一致性的解释。

如果你看一下这里的通用实现,你会发现set、map和list的实现方法是一致的。

对于set和map,我们有两个标准的哈希映射和树实现。第一个是最常用的,第二个是当我们需要一个有序结构时使用的(它也实现了自己的接口——SortedSet或SortedMap)。 我们可以使用首选的样式,如Set<String> Set = new HashSet<String>();原因见这里。

但是Stack类:1)没有自己的接口;2)是Vector类的子类-它是基于可调整大小的数组;那么堆栈的链表实现在哪里呢?

在Deque接口中,我们没有这样的问题,包括两个实现(可调整大小的数组- ArrayDeque;链表- LinkedList)。

一方面,它在继承方面更合理。在我看来,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中元素的迭代器。元素将按照从第一个(头)到最后一个(尾)的顺序返回。

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

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.