stack源码解析

Java类:stack栈

stack是一个继承Vector类用于栈的类

初始化

public Stack() {}

看看父类的构造函数,做了什么操作?

protected Object[] elementData;//数据存储
protected int capacityIncrement;//容量增量

public Vector() {
    this(10);
}

/**
 * @param initialCapacity 初始化容量,无参构造器中传入的10
*/
public Vector(int initialCapacity) {
    this(initialCapacity, 0);
}

/**
 * @param initialCapacity 初始化容量,上文传入的10
 * @param capacityIncrement 容量增量,上文传入的0
*/
public Vector(int initialCapacity, int capacityIncrement) {
    super();
    if (initialCapacity < 0)//指定的构造新数组的大小小于0,这显然是不合理的,所以直接抛出异常
        throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
    this.elementData = new Object[initialCapacity];//创建一个长度10的新数组
    this.capacityIncrement = capacityIncrement;
}

从源码可以看出,stack使用数组存储数据,并且这一切都依靠父类Vector实现

添加元素:java.util.Stack#push

public E push(E item) {
    addElement(item);//调用父类Vector方法
    return item;
}

父类Vector方法:java.util.Vector#addElement

protected transient int modCount = 0;//记录操作次数
protected int elementCount;//元素数量计数

public synchronized void addElement(E obj) {
    modCount++;//操作次数+1
    ensureCapacityHelper(elementCount + 1);//传入一个新的容量(原长度+1),构建新数组
    elementData[elementCount++] = obj;//向新数组添加对象(调用完此方法时elementCount值已发生改变)
}
protected Object[] elementData;
/**
 * 
 * @param minCapacity 所需最小扩容容量(容纳新元素的最小数组容量),上文传入值:elementCount + 1
*/
private void ensureCapacityHelper(int minCapacity) {
    // 验证所需最小扩容容量是否大于旧容量
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;//记录旧容量
    // 计算扩容容量,原则上(capacityIncrement = 0为前提)扩容后的容量是原容量2倍
    int newCapacity = oldCapacity + ( capacityIncrement > 0 ? capacityIncrement : oldCapacity);
    // 如果扩容容量仍然小于所需最小扩容容量,那么扩容容量采用所需最小扩容容量
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    // 如果扩容容量大于数组最大限,用hugeCapacity处理
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    //重新构建一个新数组,并把原数组的值拷贝过去
    elementData = Arrays.copyOf(elementData, newCapacity);
}

java.util.Vector#hugeCapacity

public static final int MAX_VALUE = 0x7fffffff;

private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    // 如果所需最小扩容容量 大于数组最大限,那么直接采用0x7fffffff,小于则采用Integer.MAX_VALUE - 8
    return minCapacity > MAX_ARRAY_SIZE ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}

弹出元素:java.util.Stack#pop

public synchronized E pop() {
    E obj;
    int len = size();//获取数组长度
    obj = peek();//获取数组中最后一个位置的对象
    removeElementAt(len - 1);//移除最后一个位置的对象
    return obj;//返回对象
}

peek

public synchronized E peek() {
    int len = size();//获取数组长度
    if (len == 0)
        throw new EmptyStackException();
    return elementAt(len - 1);//获取数组中最后一个位置的对象
}
/**
 * 获取数组中最后一个位置的对象 的具体实现
 * */
public synchronized E elementAt(int index) {
    if (index >= elementCount) {
        throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
    }
    return elementData(index);
}

java.util.Vector#size

public synchronized int size() {
    return elementCount;
}

removeElementAt

public synchronized void removeElementAt(int index) {
    modCount++;
    if (index >= elementCount) {
        throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                                     elementCount);
    }
    else if (index < 0) {
        throw new ArrayIndexOutOfBoundsException(index);
    }
    int j = elementCount - index - 1;
    if (j > 0) {
        System.arraycopy(elementData, index + 1, elementData, index, j);
    }
    elementCount--;
    elementData[elementCount] = null; //将下标所指位置赋值null,弹出元素并不会导致数组容量缩减
}

总结

从整个代码看得出来

  • stack是一个由数组实现的先进后出,后进先出的栈结构
  • 容量有限制,初始容量10,删除元素并不直接缩减容量
  • stack是线程安全的(利用synchronized锁)
  • 主要工作由Vector完成
posted @   勤匠  阅读(11)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示