jdk1.8-stack 栈源码分析

一:类的继承关系
UML图:

类的继承关系:
public
class Stack<E> extends Vector<E>
分析:栈的继承关系很简单,就是继承了Vector,那么我们可以猜测栈操作大部分应该是线程安全的。

二:类的成员属性
栈这个类除了一个版本号外,没有其它成员属性


三:看下构造方法
构造方法就一个,无参构造方法,什么也没做
/**
* Creates an empty Stack.
*/
public Stack() {
}


四:主要方法
1.push()方法
/**
* Pushes an item onto the top of this stack. This has exactly
* the same effect as:
* <blockquote><pre>
* addElement(item)</pre></blockquote>
*
* @param item the item to be pushed onto this stack.
* @return the <code>item</code> argument.
* @see java.util.Vector#addElement
*/
public E push(E item) {
//调用父类vector的addElement()方法
addElement(item);

return item;
}
分析:往栈里压入一个元素用push方法,每次往栈的顶部压入元素。addElement()是抽象父类vector方法,我们在vector里已经分析过。从这里我们可以知道,栈的底层数组结构也是数组。


2.pop()方法
/**
* Removes the object at the top of this stack and returns that
* object as the value of this function.
*
* @return The object at the top of this stack (the last item
* of the <tt>Vector</tt> object).
* @throws EmptyStackException if this stack is empty.
*/
public synchronized E pop() {
E obj;
//栈的长度
int len = size();

//栈顶部的元素值(也就是数组最后一个元素值)
obj = peek();
//栈元素减1
removeElementAt(len - 1);

//返回顶部元素
return obj;
}
分析:删除栈顶部的对象,并将该对象作为函数值返回
这里我们继续看下removeElementAt()方法,   peik()方法单独讲
/**
* Deletes the component at the specified index. Each component in
* this vector with an index greater or equal to the specified
* {@code index} is shifted downward to have an index one
* smaller than the value it had previously. The size of this vector
* is decreased by {@code 1}.
*
* <p>The index must be a value greater than or equal to {@code 0}
* and less than the current size of the vector.
*
* <p>This method is identical in functionality to the {@link #remove(int)}
* method (which is part of the {@link List} interface). Note that the
* {@code remove} method returns the old value that was stored at the
* specified position.
*
* @param index the index of the object to remove
* @throws ArrayIndexOutOfBoundsException if the index is out of range
* ({@code index < 0 || index >= size()})
*/
public synchronized void removeElementAt(int index) {
//修改次数加1
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) {
//从index + 1位置开始,向左移动一个位置,移动的个数为j
System.arraycopy(elementData, index + 1, elementData, index, j);
}
//数组实际元素减1
elementCount--;
//数组最后一个元素置为null,等待gc回收
elementData[elementCount] = null; /* to let gc do its work */
}
分析:传进来len -1,栈顶部元素下标,即数组最后一个元素位置。
数组删除当前元素通过将当前元素以后的所有元素往左移动一位,然后末尾元素置为null而达到的。
只不过这里删除的元素就是最后一位,所以j=0,并不需要再移动元素而已了。

3.peek()方法
/**
* Looks at the object at the top of this stack without removing it
* from the stack.
*
* @return the object at the top of this stack (the last item
* of the <tt>Vector</tt> object).
* @throws EmptyStackException if this stack is empty.
*/
public synchronized E peek() {
int len = size();

if (len == 0)
throw new EmptyStackException();
//根据索引从数组里取值,elementAt是调用父类Vector的方法
return elementAt(len - 1);
}
分析:栈的peek()方法,其实就是返回栈顶部的元素值,即数组末尾元素值。
peek()方法只是返回下标的值,但并不删除该元素,删除是通过上面的removeElementAt()方法。

/**
* Returns the component at the specified index.
*
* <p>This method is identical in functionality to the {@link #get(int)}
* method (which is part of the {@link List} interface).
*
* @param index an index into this vector
* @return the component at the specified index
* @throws ArrayIndexOutOfBoundsException if the index is out of range
* ({@code index < 0 || index >= size()})
*/
public synchronized E elementAt(int index) {
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
}

return elementData(index);
}
分析:这个方法就是根据下标,返回数组的值而已,没啥好分析的。

到此,栈就分析差不多了。我们可以发现,栈的实现还是相对简单的。
通过阅读源码,我们确实可以对集合的理解加深,并且对数组结构的运用有更深刻的认识。


有疑问,扫我二维码添加微信,欢迎骚扰!
坚持做一件事,一起学习。


原文地址:https://www.cnblogs.com/lizb0907/p/10561011.html