我需要一个堆栈数据结构为我的用例。我应该能够将项目推入数据结构,我只想从堆栈中检索最后一项。JavaDoc for Stack说:
一个更完整和一致的后进先出堆栈操作集是
由Deque接口及其实现提供,这应该
优先用于该类。例如:
Deque<Integer> stack = new ArrayDeque<>();
我肯定不希望在这里使用同步行为,因为我将在方法的本地使用这个数据结构。除此之外,为什么我更喜欢Deque而不是Stack呢?
附:Deque的javadoc说:
Deques也可以用作后进先出(LIFO)堆栈。这
接口应该优先于遗留的Stack类。
下面是我对Stack类描述中提到的不一致性的解释。
如果你看一下这里的通用实现,你会发现set、map和list的实现方法是一致的。
对于set和map,我们有两个标准的哈希映射和树实现。第一个是最常用的,第二个是当我们需要一个有序结构时使用的(它也实现了自己的接口——SortedSet或SortedMap)。
我们可以使用首选的样式,如Set<String> Set = new HashSet<String>();原因见这里。
但是Stack类:1)没有自己的接口;2)是Vector类的子类-它是基于可调整大小的数组;那么堆栈的链表实现在哪里呢?
在Deque接口中,我们没有这样的问题,包括两个实现(可调整大小的数组- ArrayDeque;链表- LinkedList)。
下面是我对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中元素的迭代器。元素将按照从第一个(头)到最后一个(尾)的顺序返回。