提前声明:
这里讨论的 Stack ,特指 Java 里的 Stack 类,在 Java 里,他的实现方法不好,并不是说这个数据结构不好。
Stack 有什么问题
并不是我们说 Stack 不好,就连 Java 官方也说过 Stack 这个类不好,应该用 Deque 接口来代替。
可以看出, Stack 是继承了 Vector 这个类的,那么就会有 Vector 这个类里面相应的方法(除了 private 的之外)
所以问题就来了。 我们所说的 Stack 是只能在一端进行 增加和删除 操作的一种数据结构,Vector 底层是动态数组实现,有一些方***破环我们对 Stack 这种数据结构的定义,以致于 Stack 不是 “真正的” Stack。
那官方说用 Deque 接口来代替就解决了这个问题吗? 遗憾的是并没有。
接口: 更高层次的一种抽象,定义 实现这个接口的类 应该需要满足哪些方法,对具体实现不做限制。
Deque 结构的规则是,可以在 2 端进行数据的 增加和删除 操作。而 Stack 仅仅只需要 一端 就可以了。
这同样也会破环我们的 Stack 这种数据的定义。
迄今为止,Java 也只做到了这一步,也没有对原来的 Stack 类标记为 deprecate; 也没有再写一个 CorrectStack 或 RealStack 这样的接口。
再说说官方给的 Deque 接口为什么用 ArrayDeque 实现。
Deque 还有一种实现类是 LinkedList,这是基于链表的。 而 ArrayDeque 底层是 动态数组。
在数据量比较小的时候,他们的性能差别不大。
但是,当数据量大到一定程度的时候,往后追加元素的操作,链表的性能是 远远低于 动态数组的。
比如,对于 10000000 (1000万) 的数据量:
在一个比较老式的机器上,运行的结果是:
谈谈 继承和组合 的问题
Java 中的 Stack 类的问题,是一种设计问题。 也就是 Vector 和 Stack 根本不是一种继承关系。也许用组合关系会更适合一些。
继承关系, 是一种 is-a 的关系。 组合关系,是一种 has-a 的关系。
判判 2 个类是哪种关系,就看这否用向上转型为父类的可能,如果有,那继承关系会方便些,如果没有,哪就是组合关系。
面向对象设计原则中,有一条是 : Composition over inheritance 。也就是应该优先考虑组合模式。
如果 Stack 和 Vector 设计成组合模式,那代码就应该是这样:
public class Stack<E>{
private Vector<E> arr;
}