JAVA容器——Stack(JAVA8) 源碼解析

    一 棧簡介

    棧是一種常用的線性抽象數據結構,在計算機中應用極爲廣泛。棧有兩個爲人熟知的特性,一是進出棧的順序是先進後出(FILO),即最先進棧的數據最後出棧,當然相對的也有後進先出(LIFO),最後進棧的數據先出棧。另一個是支持兩個通用操作:Push:將元素推進棧;Pull:從棧中取出數據。

    棧的操作演示見下圖,這裏需要注意的是1的位置對應的是棧底,後面再Push的元素所在位置爲棧頂,所有對棧的操作,都

是在棧頂操作。

                                                                         圖1 棧操作示意圖

 二 Java棧實現

    Java棧繼承自Vector,關係圖如下:

                                                                             圖2 Java Stack繼承關係圖

    在前面的文章Java Vector源碼解析解析中,我們已經對Vector做了介紹,這是一種加鎖實現的List。Stack是從Vector中擴展而來, 功能相對要簡單許多,下面看看具體實現。

                                                                                圖3 Java Stack實現

/**
 *
 * <p>A more complete and consistent set of LIFO stack operations is
 * provided by the {@link Deque} interface and its implementations, which
 * should be used in preference to this class.  For example:
 * <pre>   {@code
 *   Deque<Integer> stack = new ArrayDeque<Integer>();}</pre>
 *
 * @author  Jonathan Payne
 * @since   1.0
 */
public
class Stack<E> extends Vector<E> {
    /**
     * Creates an empty Stack.
     */
    public Stack() {
    }

    /**
     * Pushes an item onto the top of this stack. 
     */
    public E push(E item) {
        addElement(item);

        return item;
    }

    /**
     * Removes the object at the top of this stack and returns that
     * object as the value of this function.
     */
    public synchronized E pop() {
        E       obj;
        int     len = size();

        obj = peek();
        removeElementAt(len - 1);

        return obj;
    }

    /**
     * Looks at the object at the top of this stack without removing it
     * from the stack.
     */
    public synchronized E peek() {
        int     len = size();

        if (len == 0)
            throw new EmptyStackException();
        return elementAt(len - 1);
    }

    /**
     * Tests if this stack is empty.
     *
     */
    public boolean empty() {
        return size() == 0;
    }

    /**
     * Returns the 1-based position where an object is on this stack.
     * If the object {@code o} occurs as an item in this stack, this
     * method returns the distance from the top of the stack of the
     * occurrence nearest the top of the stack; the topmost item on the
     * stack is considered to be at distance {@code 1}. The {@code equals}
     * method is used to compare {@code o} to the
     * items in this stack.
     *
     * @param   o   the desired object.
     * @return  the 1-based position from the top of the stack where
     *          the object is located; the return value {@code -1}
     *          indicates that the object is not on the stack.
     */
    public synchronized int search(Object o) {
        int i = lastIndexOf(o);

        if (i >= 0) {
            return size() - i;
        }
        return -1;
    }

}

    由於代碼比較少,這裏把基本都貼出來了。從繼承關係可以看出,Stack就是一個閹割了的Vector。Vector本質上是一個數組,所以Stack也是由數組實現。方法實現的方式如下:

  • Push:將元素添加到棧的最後,也即數組的末尾;
  • Pop:將棧末尾的元素取出並刪除;
  • Peek:取出最後一個元素,但不從棧中刪除;
  • Search:查找元素距離棧頂的位置;

    這裏需要注意的是,上面的操作都是加鎖了的,也即是線程安全的,因此Stack本身是一個線程安全的數據類型,當然這也導致了它的性能會受到影響。

    三 小結

    請關注類開頭的註釋:more complete and consistent set of LIFO stack operations is provided by the {@link Deque} interface and its implementations, which should be used in preference to this class. For example:
    Deque<Integer> stack = new ArrayDeque<Integer>();

    官方推薦使用雙向隊列來實現棧,而不是再繼續使用Stack這個數據結構。當然Stack的實現方式還是有一定參考價值的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章