我需要一个堆栈数据结构为我的用例。我应该能够将项目推入数据结构,我只想从堆栈中检索最后一项。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将时间从7.6分钟缩短到1.5分钟。

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

下面是我对Stack类描述中提到的不一致性的解释。

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

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

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

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

如果出于某种原因你想从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);

使用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]