在实际的运用过程中我们经常会运用先进后出的栈结构,但是我们不推荐使用java的栈,虽然个人并不是很赞同它的设计不雅,因为即使Stack的设计不符合设计的原则,但是并不影响它的正确性。
为什么不推荐使用Java自带的Stack
本文主要解决自己在阅读HashMap源码过程中碰到的一些疑惑,进行记录,接下来将会介绍HashMap相关的源码实现。
- 设计层面。Java 中的 Stack 实现,是被业界一直认为非常糟糕的实现。实际上,它犯了面向对象设计领域的一个基本错误:Stack 和 Vector 之间的关系,不应该是继承关系,而应该是组合关系(composition)。
- 实用层面。最大的问题在于,继承使得子类继承了父类的所有公有方法。而 Vector 作为动态数组,是有能力在数组中的任何位置添加或者删除元素的。因此,Stack 继承了 Vector,Stack 也有这样的能力!
1 | Stack<Integer> stack=new Stack<>(); |
如何区分组合和继承的使用场景
- 继承关系描述的是is-a 的关系,即“是一个”的关系。
- 猫是一个动物,所以猫这个类可以继承动物类。
- 程序员是一个雇员,所以程序员这个类可以继承雇员类。
- 组合关系描述的是has-a 的关系,即“有一个”的关系。
- 车里有一台发动机,所以发动机这个类和车这个类之间,应该是组合关系,即车中包含一个成员变量,是发动机这个类的对象。
- 电脑里有 CPU,内存,显卡。所以 CPU,内存,显卡,这些类和电脑类之间的关系,都应该是组合关系。
用双端队列Deque实现Stack操作
双端队列当然可以实现栈的操作,但是基于Deque自己封装一个Stack似乎会更好,因为Deque仍然会有两端都可以移动的问题,正常情况下Stack是不允许两端移动的。
总结
说白了就是大家认为Stack的继承设计有问题,导致提供了父类可能导致错误的API。推荐大家用ArrayDeque或者LinkedList自己实现一个Stack。