JAVA容器——Stack(JAVA9) 原始碼解析
一 棧簡介
棧是一種常用的線性抽象資料結構,在計算機中應用極為廣泛。棧有兩個為人熟知的特性,一是進出棧的順序是先進後出(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的實現方式還是有一定參考價值的。