专栏首页渔夫Java 中的 Vector、Stack 与 ArrayList

Java 中的 Vector、Stack 与 ArrayList

引子:首先不得不说, Vector 与 Stack 这一对继承设计是蹩脚、失败的。


比如见于 coderanch 的一个问题:

Stack extends Vector !

 The java.util.Stack extends the Vector class. But for Stack, one should be able to insert or retrive the value from only one side i.e at the top of the stack. But since Stack extends Vector, we can use the inherited get(int index) method to access value other than the top of the stack value. It defeats the purpose of Stack, right? Then why does Stack extends Vector. Any explaination ?? Thanks in advance.

 回答是这样的:

 The Stack class represents a last-in-first-out (LIFO) stack of objects. It extends class Vector with five operations that allow a vector to be treated as a stack. The usual push and pop operations are provided, as well as a method to peek at the top item on the stack, a method to test for whether the stack is empty, and a method to search the stack for an item and discover how far it is from the top.

 也就是说,在本质上 Java 中实现的 Stack 就是一个 Vector。上述回答可以用以下代码归纳:

import java.util.Stack;
import java.util.Vector;

public class Test {
    public static void main(String[] args) {
        Vector<String> vector = new Stack<>();
        vector.add("hello");
        vector.add("world");

        //用于证明 Stack 对象也可以使用 Vector 的get(int index)方式得到
        for (int i = 0; i < vector.size(); i++) {
            System.out.println(vector.get(i));
        }
        System.out.println("-----");

        //用于证明可以使用 Stack 对象的peek方法
        Stack stack=(Stack)vector;
        System.out.println(stack.peek());
        System.out.println("-----");

        //用于证明可以使用 Stack 对象的 pop 方法
        while(!stack.empty()){
            System.out.println(stack.pop());
        }

        //用于证明 Stack 对象在元素都弹出后内部元素为0
        System.out.println(vector.size());
        
    }
}

控制台输出:

hello
world
-----
world
-----
world
hello
0

使用 Vector 实现的 Stack 是个好主意吗?

 Vector 其内部是由一个 Object 类型会自动扩容的数组进行存储元素。而 Java 编程思想的作者写到:Stack is inherited from Vector, which says that a Stack is a Vector, which isn’t really true from a logical standpoint. 逻辑上说,栈应该是一个队列。

 除了继承逻辑上的出现的问题,Vector 设计差更体现在效率上。对于 Vector类 以及 Stack类 最大的问题在于对 synchronized 同步关键字的滥用。这个类的公共方法几乎都使用了 synchronized 关键字。这一点你是不会愿意看到的,至少这种确保并发安全的方式太粗粒度了。这两个类作为 Java 的标准类库中的类,这么设计是不合适,因为这可是面对所有 Java 用户的。效率差则体现在:一般而言,在同步锁中我们会进行一系列操作,这是因为获得/释放锁是一项有时间开销的操作。但是如果数据结构是 Vector 或 Stack,那么你的每个单独操作,比如添加一个元素就要进行一次获得/释放锁。如果你需要批量添加元素,那么将有O(n)次的获得以及释放锁,效率极差。而且因为存在类内方法的相互调用,产生了很多没有必要的锁的重载。

 所以说基本上,在大多数情况下,这是一个非常有缺陷的同步方法。Vector 以及 Stack 类本质上可以认为是以下两点结合的产物:

  • 容量大小可变的数组;
  • 每个方法都使用 synchronized 修饰;

 如果你实现打算使用数据结构 Stack ,那么不妨使用 ArrayList 以及 ArrayQueue。

历史原因

 据说,Java 之所以提供这样一个糟糕的类是由于在 Java 发布第一个版本的时候,Java 希望于抢先发布以抢占市场。一些与早期版本捆绑在一起的 Java 类并没有经过深思熟虑。它们并没有经过同行评议和公共审查。例如通过 Java Community Process 、开源项目以及协会项目发布的一些库。Vector 和 Stack 就是属于这些库中的类,并作为一个标准库的蹩脚类存在。再比如 java.util.Date/.Calendar类也是相当蹩脚的存在,Java 为了向后兼容性保存了一部分类,但是不建议在新的代码中使用。

 JavaDoc 也给出了不要使用的建议,以及给出了一个新的方法创建 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>();

ArrayList

 至于 ArrayList,其在 JDK 1.2 时加入 Java 标准类库。我们完全可以将其认为是没有进行同步操作的可变大小数组容器。此类的 Java Doc 在第一段写到:

 This class is roughly equivalent to Vector, except that it is unsynchronized.

而 ArrayDeque 中的 JavaDoc 写到:

 This class is likely to be faster than Stack when used as a stack, and faster than LinkedList when used as a queue.

可见一斑。

参考网址:

  • https://stackoverflow.com/questions/1386275/why-is-java-vector-and-stack-class-considered-obsolete-or-deprecated
  • https://stackoverflow.com/questions/37314298/why-stack-extends-vector-in-jdk

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 从强耦合到行为化参数最终到 Lambda 表达式

     首先给出本次讨论的背景。农民希望你能够进行苹果库存的筛选,不过他作为甲方,需求经常会改变。

    Fisherman渔夫
  • Java-单向链表-从实现到各类操作(全家桶,包含各类常见方法)

    版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons)

    Fisherman渔夫
  • 算法题-1比特与2比特字符

    版权声明: ...

    Fisherman渔夫
  • JFrog Xray如何实现组件安全精准管理

    在安全管理的工作中常常遇到互联网上新发布了一个包的漏洞,此时部门需要立刻知道这个包的引用情况。遇到这种情况,安全管理部门往往是采用发邮件让开发人员进行自查,并要...

    JFrog杰蛙科技
  • 学界 | 超越ImageNet:谷歌内建300M图像数据集揭露精度与数据的线性增长关系

    F选自Google Research 机器之心编译 参与:蒋思源、路雪 自残差网络以来,深度模型拥有了极大的容量,同时 GPU、TPU 等硬件为深度学习提供了巨...

    机器之心
  • [有人@我]免费送书你不要?

    南风
  • 漂亮很重要!UI设计师必备的7种色彩搭配方案

    合理运用色彩是每个设计师都应必须具备的技能,特别是插画师和UI设计师。色彩理论知识的重要性也变得愈加明显!

    用户5009027
  • 20年前的吴恩达,藏在一个数据集里

    今天这张照片火了。连正主吴恩达都在推特上转发了这张黑白照片。吴恩达回忆说,这张照片拍摄于大概20年前~

    量子位
  • 基于区块链技术的数据共享赋能AI驱动网络

    人工智能和机器学习算法的最新发展为网络自动化提供了动力。最近,移动网络运营商(MNO)正在使用以人工智能为基础的模块,通过在其租用/自有区域内授权的数据进行网络...

    区块链大本营
  • IROS 2019 机器视觉全球挑战赛:赋予 AI 终生学习能力(附冠军算法模型)

    多位机器人领域大咖来到现场进行特邀报告和圆桌讨论,包括:意大利技术研究院科学主任 Giorgio Metta 教授、汉堡大学张建伟教授、浙江大学章国锋教授等知名...

    AI研习社

扫码关注云+社区

领取腾讯云代金券