正如评论中已经提到的那样,我们有经过充分测试的Deque
接口,应该优先考虑使用。
但我会告诉你为什么不应该使用Stack
。
首先,Java Doc. 中的 Stack 说:
A more complete and consistent set of LIFO stack operations is
provided by the Deque interface and its implementations, which should
be used in preference to this class. For example:
Deque<Integer> stack = new ArrayDeque<Integer>()
请查看JavaDoc。
那么Stack
类有什么问题呢?
就像Martin Fowler在他的书中所提到的那样,使用重构方法Replace Inheritance with Delegation时,栈不应该继承自向量。
不适当的继承的经典例子之一是将栈作为向量的子类。 Java 1.1在其实用程序中这样做(淘气的男孩!)[6,p.288]
相反,他们应该像下面的图片一样使用委托,这也是来自该书的内容。
还可以在此处查看:Replace Inheritance with Delegation
那么,为什么这是个问题:
因为堆栈只有5个方法:
- pop
- push
- isEmpty
- search
- size
size()
和isEmpty()
是从Vector
类继承而来的,而Vector
的其他方法没有被使用。但是通过继承,其他方法被转发到了Stack
类中,这是没有意义的。
对于这个问题,Fowler提出了以下建议:
你可以忍受这种情况,并使用惯例来表示,尽管它是一个子类,但它只使用了超类的一部分功能。但是这会导致代码表达了一件事情,而你的意图是另一件事情——这是一个你应该消除的混淆。
这违反了接口隔离原则
该原则指出:
客户不应被强制依赖于他们不使用的接口。
你可以查看
Vector 和
Stack 类的源代码,你会发现 Stack 类继承了 spliterator 方法和 VectorSpliterator 内部类,这些都来自于 Vector 类。
这个方法被 Collection 接口用来实现 stream 方法的默认版本:
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
因此,避免简单地使用Vector
和Stack
类。
[6] 重构:改善现有代码的设计,Martin Fowler著,1997年。
Deque
(以及其实现类)甚至没有stream()
方法。问题不在于我是否可以解决它(我显然可以编写自己的循环)。问题是为什么 Stack 提供了流方法并以错误的方式进行流,当我们期望使用所选集合的 LIFO 排序时。 - jbxstream()
方法,来自java.util.Collection。但是我这里没有Java 8,所以无法测试它。 - azurefrogDeque
它可以正常工作!为什么会这样呢?(我只是将Stack
更改为Deque
) - jbxStack
只是一个奇怪的突变Vector
。实际上,我认为在调用stream()
时打破直觉排序可能是你想要添加到https://dev59.com/EnE85IYBdhLWcg3wJQAa的内容。 - azurefrogVector
的类。我已经使用LinkedList
和ArrayDeque
进行了测试,如果我使用push()
方法添加项目,那么stream()
方法将正确地反转它们的顺序。 - jbx