栈只允许访问一个数据项:即最后插入的数据项。
只能对栈顶进行操作,后进先出(LIFO)。
类Stack继承于Vector
push操作:
public E push(E item) {
addElement(item);
return item;
}
其中addElement(item)是父类vector的一个方法,由于vector是基于数组实现的,所以要先检查容量是否足够
public synchronized void addElement(E obj) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = obj;
}
其中modCount是定义在vector的父类AbstracList中的一个整数,在栈中,这个变量用来记录共有多少次进出栈操作。
protected transient int modCount = 0;
ensureCapacityHelper(int s)方法用来给数组容器扩容。
protected int elementCount;是vector中的成员变量,用来记录当前共有多少可用值
扩容方法,如果有设置增量大小,那么就扩那么大,否则增加一倍的容量。如果扩一倍超过了最大限制,或者扩大增量后仍小于需要的容量,那么扩至需要的容量,由此可见:
当数组容量达到最大容量的一半以上时,如果没有设置固定增量,那么每插入一个元素都需要扩容数组,那么性能必然很低。
而如果是批量插入,并且批量插入的数量大于固定增量,也会导致每次批量插入都需要扩容,性能也会很低。
确定容量之后,调用Arrays的方法对数组扩容。
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);
}
pop操作,从栈中取出栈顶元素
public synchronized E pop() {
E obj;
int len = size();
obj = peek();//获取当前栈顶元素
removeElementAt(len - 1);//移除栈顶元素
return obj;
}
size()方法实现为
public synchronized int size() {
return elementCount;
}
peek()方法是获取当前最后一个元素
public synchronized E peek() {
int len = size();
if (len == 0)
throw new EmptyStackException();
return elementAt(len - 1);
}
elementAt(int i)获取在位置i处的元素,该方法在vector中实现
public synchronized E elementAt(int index) {
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
}
return elementData(index);
}
E elementData(int index) {
return (E) elementData[index];
}
removeElementAt(int index)用来移除数组中位置Index处的元素,在vector中实现。
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;//在栈操作中,j是永远等于0的。
if (j > 0) {
System.arraycopy(elementData, index + 1, elementData, index, j);//把index处的元素移除,并把后面的元素前移一位。用C++实现。对于栈对象,这里不会执行
}
elementCount--;
elementData[elementCount] = null; /* 置为null,让gc及时回收*/
}