什么是Stack
- Stack就是栈,是一个重要的数据结构,它具有
先进后出
的特点。 - 栈的入栈和出栈操作都在栈顶进行,也可以说是在栈的尾部进行。所以先存的要在后面才能取出来,所以栈具有先进后出的特点。
源码解析
栈的底层结构
首先我们查看一下api 可以发现Stack继承的是Vector
类,由此我们可以得出,栈的底层也是一个数组
构造方法
栈的构造方法只有一个
public Stack() {
}
创建一个空栈,这里我们不禁有一个疑问,既然它继承了Vector,它的父类是有一个默认容量的,为10,那么Stack的构造方法只有一个,且没有默认大小,那么它是怎么进行扩容的呢,这时候我们去查看它的push()
方法,Stack直接调用了Vector类的addElement(E item)
方法
public E push(E item) {
addElement(item);
return item;
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
可以看到,是在计算插入数据后容量大小与原来容量大小做比较,除非栈满了,才会进行扩容。扩容调用的就是grow(minCapacity)
。
Stack中的方法
push()
用于向栈中添加元素,这里调用的是Vector的addElement方法
public E push(E item) {
addElement(item);
return item;
}
peek()
-
该方法用于查看栈顶对象而不移除它
-
这里调用了它的父类中的size方法计算栈的高度,然后如果长度为0,说明栈为空,抛出一个空栈异常,如果不为空,则调用Vector中的elementAt方法获取索引为长度减一的这个元素并返回这个元素,也就是最后一个元素(即栈顶元素)。
public synchronized E peek() {
int len = size();
if (len == 0)
throw new EmptyStackException();
return elementAt(len - 1);
}
pop()
该方法用于移除栈顶对象并作为此函数的值返回该对象。
public synchronized E pop() {
E obj;
int len = size();
obj = peek();
removeElementAt(len - 1);
return obj;
}
empty()
用于判断这个栈是否为空
public boolean empty() {
return size() == 0;
}
我们可以看到,这里对于栈顶的操作的方法都是带有线程锁的,这是因为栈顶是栈的出入口,如果在查看的同时有程序去进行存取的话,会乱套,所以加上线程安全锁来保证它的安全。