Stack源码分析

Stack源码分析

Stack继承自VectorStack本身的方法很少,大多数都是依赖父类Vector的。

构造方法

    public Stack() {
    }

功能方法

empty

    public boolean empty() {
        return isEmpty();
    }

    // Vector.java
    @Override
    public synchronized boolean isEmpty() {
        return elementCount == 0;
    }
  • 判断是否为空,直接调用父类。
  • 因为Stack本身是没有什么属性的,只有一个序列号id。精华都在Vector身上。Stack只是针对栈的特性增加了如:peek/pop等方法

peek

    @SuppressWarnings("unchecked")
    public synchronized E peek() {
        try {
            return (E) elementData[elementCount - 1];
        } catch (IndexOutOfBoundsException e) {
            throw new EmptyStackException();
        }
    }
  • peek方法返回数组的最后一个元素
  • 栈的特性就是:先进后出或后进先出
  • 因此,最后进来的元素一定是最先出去的。

push

    public E push(E object) {
        addElement(object);
        return object;
    }

    // Vector.java
    public synchronized void addElement(E object) {
        // 1.如果容量已满,就进行数组扩容
        if (elementCount == elementData.length) {
            growByOne();
        }
        // 2.在数组最后添加元素
        elementData[elementCount++] = object;
        modCount++;
    }
  • push方法也是调用父类的方法实现。
  • 将元素添加到数组最后
  • Stack的方法已经确定了,只能从数组的尾端进行存/取操作。
    public synchronized int search(Object o) {
        final Object[] dumpArray = elementData; // 存储元素的数据
        final int size = elementCount; // 元素的个数
        if (o != null) { // 如果要查的数据不为null
            for (int i = size - 1; i >= 0; i--) { // 从数组尾部开始向前遍历
                if (o.equals(dumpArray[i])) { // 遇到相同的就返回
                    return size - i;
                }
            }
        } else { // 如果要查的数据为null
            for (int i = size - 1; i >= 0; i--) { // 从数组尾部开始向前遍历
                if (dumpArray[i] == null) { // 遇到相同的就返回
                    return size - i;
                }
            }
        }
        return -1;
    }
  • Vector里的containsindexOf等方法的实现方式类似。

pop

    @SuppressWarnings("unchecked")
    public synchronized E pop() {
        if (elementCount == 0) {
            throw new EmptyStackException();
        }
        final int index = --elementCount;
        final E obj = (E) elementData[index];
        elementData[index] = null;
        modCount++;
        return obj;
    }
  • 元素个数--,赋值给index。此时index就是最后一位元素的索引
  • 取得值obj,置为null,返回obj
  • peek一样都是取得**最后一位元素**,不同的是pop会取得的同时删除最后一位元素。而peek`不会。

总结

  • StackVector很像,大部分都是由Vector实现的。
  • Stack只不过一招FILO的规则,自定义了push/pop/peek等方法。
  • 理解了VectorStack看一遍就懂了!
### 关于 Stack 数据结构的源码解析 #### Java 中 `java.util.Stack` 类的实现 Java 提供了一个名为 `Stack` 的类作为其标准库的一部分,该类继承自 `Vector` 并实现了栈的功能。以下是对其内部工作原理的一些深入探讨: - **构造函数** 构造一个新的空堆栈。 ```java public class Stack<E> extends Vector<E> ``` - **核心方法** - `push(E item)` 方法用于将项压入此堆栈顶部。这实际上是调用了父类 `Vector` 的 `addElement()` 方法来增加元素到列表末端[^1]。 ```java public E push(E item) { addElement(item); return item; } ``` - `pop()` 方法移除并返回位于堆栈顶端的对象。如果尝试从空堆栈弹出,则抛出异常。它通过调用 `elementAt(size() - 1)` 获取最后一个元素,并随后删除这个位置上的对象。 ```java public synchronized E pop() { if (empty()) { throw new EmptyStackException(); } E obj = peek(); removeElementAt(size() - 1); return obj; } ``` - `peek()` 返回但不移除此堆栈顶部的对象;如果堆栈为空则返回 null 或者抛出 NoSuchElementException 异常取决于具体版本的行为。 ```java public synchronized E peek() { int size = size(); if (size == 0) { throw new EmptyStackException(); } return elementAt(size - 1); } ``` - **线程安全性** 因为 `Stack` 继承自 `Vector` 而后者是一个同步容器,所以所有的操作都是线程安全的。然而,在多线程环境中使用时仍需注意潜在的竞争条件和其他并发问题。 对于更高效的非阻塞数据结构或者想要避免遗留 API 带来的性能开销,可以考虑采用其他第三方库如 Google Guava 或 Apache Commons Collections 所提供的替代方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值