官方介绍:
继承Vector类,再加了五个方法,实现了Stack的LIFO
protected Object[] elementData; // 底层数据结构
protected int elementCount; // 有效的元素数量
/**
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
为什么一开始的最大容量要设为Integer.MAX_VALUE - 8?
是否减8没那么重要(只是为了避免一些机器内存溢出),最大长度依然是Integer.MAX_VALUE,并不是Integer.MAX_VALUE-8,看源码就知道,扩容那里,如果超过了之前设置的最大值,就直接按 Integer.MAX_VALUE处理。
而为什么会有这个最大长度,一是因为记录容器size的数据是一个int类型。
push方法
public E push(E item) {
addElement(item);
return item;
}
public synchronized void addElement(E obj) {
modCount++; // Stack的修改次数
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = obj;
}
push方法中需要确保容量:
private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity); // capacityIncrement在构造Vector函数的时候初始化,否则为0;则(暂定)新容量是旧容量的两倍
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity; // 如果求出来的新容量比需要的容量还要小,则直接将新容量设为所需容量
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity); //
elementData = Arrays.copyOf(elementData, newCapacity); // 用了这个方法,来把旧数组的内容放到新数组中,底层调用的是native方法
}
pop方法:
public synchronized E pop() {
E obj;
int len = size(); // return elementCount
obj = peek();
removeElementAt(len - 1);
return obj;
}
public synchronized void removeElementAt(int index) { // 这里调用的是Vector里的方法,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); // 也是一个native方法,但在这里用不到,因为j=0;
//public static void arraycopy(Object src,int srcPos, Object dest,int destPos,int length)
}
elementCount--;
elementData[elementCount] = null; /* to let gc do its work */
}
peek和empty方法都很简单
public synchronized E peek() {
int len = size();
if (len == 0)
throw new EmptyStackException();
return elementAt(len - 1);
}
search方法:
public synchronized int search(Object o) {
int i = lastIndexOf(o); // 因为search是要求离栈顶最近的满足要求的元素,所以正好调用这个方法
if (i >= 0) {
return size() - i; // 返回的是离栈顶的距离
}
return -1;
}
public synchronized int lastIndexOf(Object o, int index) {
if (index >= elementCount)
throw new IndexOutOfBoundsException(index + " >= "+ elementCount);
if (o == null) {
for (int i = index; i >= 0; i--) // 因为是lastIndex,所以从后往前搜索
if (elementData[i]==null)
return i;
} else {
for (int i = index; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
} // 可以学习一下这里对于null和普通元素的处理
return -1;
}