为什么我应该使用 Deque 而不是 Stack?

新手上路,请多包涵

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

Deque 接口及其实现提供了一组更完整和一致的 LIFO 堆栈操作,应优先使用此类。例如:

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

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

PS:来自 Deque 的 javadoc 说:

双端队列也可以用作 LIFO(后进先出)堆栈。应优先使用此接口而不是遗留 Stack 类。

原文由 Geek 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
2 个回答

一方面,它在继承方面更明智。 Stack extends Vector 的事实在我看来真的很奇怪。在 Java 的早期,继承被过度使用 IMO - Properties 是另一个例子。

对我来说,您引用的文档中的关键词是 consistentDeque 公开了一组操作,这些操作都是关于能够从集合的开头或结尾获取/添加/删除项目,迭代等 - 仅此而已。故意没有办法按位置访问元素,它 Stack 公开 ,因为 它是 Vector 的子类。

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

同样正如评论中指出的那样, StackDeque 具有反向迭代顺序:

 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

Deque.iterator() 的 JavaDocs 中也对此进行了解释:

以正确的顺序返回此双端队列中元素的迭代器。元素将按从第一个(头)到最后一个(尾)的顺序返回。

原文由 Jon Skeet 发布,翻译遵循 CC BY-SA 4.0 许可协议

以下是 Deque 优于 Stack 的几个原因:

面向对象设计——继承、抽象、类和接口:Stack是一个类,Deque是一个接口。只能扩展一个类,而 Java 中的单个类可以实现任意数量的接口(类型的多重继承)。使用 Deque 接口消除了对具体 Stack 类及其祖先类的依赖,并为您提供了更大的灵活性,例如,可以自由地扩展不同的类或交换 Deque 的不同实现(如 LinkedList、ArrayDeque)。

不一致:Stack 扩展了 Vector 类,它允许您通过索引访问元素。这与 Stack 实际应该做的不一致,这就是 Deque 接口是首选的原因(它不允许这样的操作)——它允许的操作与 FIFO 或 LIFO 数据结构应该允许的一致。

性能:Stack 扩展的 Vector 类基本上是 ArrayList 的“线程安全”版本。同步可能会对您的应用程序造成重大性能影响。此外,使用不需要的功能扩展其他类(如 #2 中所述)会使您的对象膨胀,可能会消耗大量额外的内存和性能开销。

原文由 Arpit Bhargava 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题