Java中stack总结

尽管人生有那么多的徒劳无功,为了梦想,我还是要一次次全力以赴。

背景与引言:

今天在做一道算法题的时候,看到了有关于算法的,而题目中扯到了栈的知识,以前了解过一点,没有深入了解过,嘿嘿,这几天把Java八大数据接口都总结一下,本人才疏学浅,只是想把我自己遇到的问题和学到的东西总结一下,再就是让大家也指出我文章中的问题,谢谢。

题目做的是力扣上的,名字叫 有效的括号

看到一种解法是使用的是,Stack的pop与push,这种解发做出来的,看了他的解法和我的解法,我默默留下了悔恨的眼泪,所以今天好好学学Stack的相关知识。

什么是Stack?

图源自百度:
在这里插入图片描述

虽然百度解释 的比较笼统,但是关于栈的几个要点已经出来了,第一:栈的特点就是 ** 后进先出**,
什么是后进先出,这张图带你了解
在这里插入图片描述
压栈也就是进栈,是后面进来的会在上面,那么,自然弹栈也就是出栈,也只能从上面的先出

第二点: Stack继承了Vector,那什么是Vector,我都先只笼统的说一下,等下实际那肯定是得看源码的,学会看源码,你才会走的更远。
Vector:
Vector 类实现了一个动态数组。和 ArrayList 很相似,但是两者是不同的:
Vector 是同步访问的。
Vector 包含了许多传统的方法,这些方法不属于集合框架。
Vector 主要用在事先不知道数组的大小,或者只是需要一个可以改变大小的数组的情况。

Vector 类支持 4 种构造方法。

第一种构造方法创建一个默认的向量,默认大小为 10:

Vector()

第二种构造方法创建指定大小的向量。

Vector(int size)

第三种构造方法创建指定大小的向量,并且增量用 incr 指定。增量表示向量每次增加的元素数目。

Vector(int size,int incr)

第四种构造方法创建一个包含集合 c 元素的向量:

Vector(Collection c)

以上大概就是Vector的一些介绍,接下来,我们一起跟随源码来深入解读Stack。

push方法,其实它调用的是 Vector中的 addElement方法

在这里插入图片描述
因为加了 synchronized,所以是线程安全的,自然效率就低
在这里插入图片描述

核心方法 grow
在这里插入图片描述

**

源码解读:

**

//真正存放element的数组
protected Object[] elementData;
 
//数组的真实长度
protected int elementCount;
 
//向量增量
protected int capacityIncrement;
	//首先add方法被synchronized修饰,表示该方法是线程安全的
public synchronized void addElement(E obj) {
		//与ArrayList的add方法一样,modCount 表示修改次数。每次新增对象就会加1
        modCount++;
        //elementCount表示底层数组中存放对象的真实数量,每次新增对象时,真实数量就要加1
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = obj;
    }
 
 
private void ensureCapacityHelper(int minCapacity) {
	
	// minCapacity表示最小容量,假如原来数组中有10个对象,那么新增1个对象,那么最小容量就是11,否则装不下
	// 最小容量减去数组的真实容量,如果大于0,就执行扩容操作
	if (minCapacity - elementData.length > 0)
	
		//真正扩容的方法,grow 表示 生长的意思
		grow(minCapacity);
}
 
 
private void grow(int minCapacity) {
	
	// 获取数组的真实容量(实际存放成员的个数)
	int oldCapacity = elementData.length;
	
	// 由于capacityIncrement = 0 ,因此newCapacity = oldCapacity + oldCapacity
	int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
									 capacityIncrement : oldCapacity);
	if (newCapacity - minCapacity < 0)
		newCapacity = minCapacity;
	if (newCapacity - MAX_ARRAY_SIZE > 0)
		newCapacity = hugeCapacity(minCapacity);
	// 将数组容量扩容至原来的2倍,并保留原数据
	elementData = Arrays.copyOf(elementData, newCapacity);
}

其中add方法与其类似,只不过add返回了一个boolean值,而addElement无返回值

实际上这个addElement方法就是每次判断数组是否满了,未满则直接将元素放入栈顶,如果满了则将栈的空间在旧elementData.length的基础上扩充一倍,然后将新的元素放入栈顶。

总结
1.调用无参构造器创建Vector

    ①首次将底层数组的容量先被初始化为10。

    ②当Vector底层数组被填满后,再次add对象时,底层数组的容量会扩容至原来的2倍,并将原数组数据拷贝进来。

3.调用有参构造器创建Vector

    ①首先将底层数组初始化为指定入参的大小。

    ②当ArrayList底层数组被填满后,再次add对象时,底层数组的容量会扩容至原来的2倍,并将原数组数据拷贝进来。## 标题

pop方法解读:

出栈时,先通过peek方法拿到栈顶元素,然后删除栈顶元素,返回元素。pop方法也是线程安全的,注意这里,与peek方法的区别,pop会拿到栈顶元素并删除,而peek只会拿到栈顶元素,并不会删除

 public synchronized E pop() {
        E       obj;
        int     len = size();

        obj = peek();
        //移除栈顶的元素
        removeElementAt(len - 1);

        return obj;
    }

删除元素也是通过父类Vector里面的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; /* to let gc do its work */
    }

这里的System.arraycopy(elementData, index + 1, elementData, index, j);实际上就是将整个elementData数组从index+1开始向前移一位,将index所在位置的值覆盖掉,以此来达到remove的效果,复制后将栈顶置空,方便GC回收内存。在pop方法中,传入的是len-1,因此每次 pop 都只会移除栈顶上的元素。System.arrayCopy方法如下

/**
 *将 源数组src 从起点位置srcPos开始的lenght长度的部分,
 *复制到目标数组的destPos位置
 * @param      src      源数组.
 * @param      srcPos   源数组的起点位置.
 * @param      dest     目标数组.
 * @param      destPos  (复制的内容放在)目标数组的开始位置.
 * @param      length   需要copy的数组长度.
*/
public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

能力有限,希望,我的总结能帮到各位,如有不对,请不吝赐教,谢谢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值