這篇文章開始介紹Stack。從名字看他就是一個stack,因此具有數據結構中棧的一般特性(後進先出),平時用起來相對較多一點,但是也是非常簡單。這篇文章我們將從源碼的角度來分析一下Stack。
OK,開始今天的文章。
一、認識Stack
Stack繼承自Vector。底層是通過數組實現的。下面我們認識一下Stack在整個java集合體系中的位置:
我們會發現,其實Stack就是繼承自Vector,因此它具有Vector的一般特點。我們把Stack放大,從Stack的角度來看一下:
從上圖我們可以看到,Stack其實就是繼承了Vector,Vector具有的接口的父類,Stack也有。
繼承了AbstractList、實現了Enumeration、List、ListIterator等接口。
下面我們再來看一下源碼,它的源碼那是超級簡單。
二、源碼分析
一下源碼基於jdk1.8來分析的。
(1)構造方法
public Stack() {}
只有一個無參構造方法。
(2)增加元素
public E push(E item) {
addElement(item);
return item;
}
這裏面調用了addElement方法,我們追蹤進去,繼續往裏看
public synchronized void addElement(E paramE) {
this.modCount += 1;
ensureCapacityHelper(this.elementCount + 1);
this.elementData[(this.elementCount++)] = paramE;
}
synchronized 說明了這是一個線程安全的方法,他分了三步走的戰略:
- 第一步:它在添加元素的時候首先將modCount加1,保證線程安全。
- 第二步:ensureCapacityHelper()主要用於保障Stack的容量,在合理範圍
- 第三步:真正實現元素的添加,將該元素添加到棧頂,數目加1;
(3)刪除元素
public synchronized E pop() {
E obj;
int len = size();
obj = peek();
removeElementAt(len - 1);
return obj;
}
在這裏我們發現,真正實現刪除操作的是removeElementAt;我們追蹤進去:
public synchronized void removeElementAt(int paramInt) {
this.modCount += 1;
if (paramInt >= this.elementCount)
throw new ArrayIndexOutOfBoundsException(paramInt + " >= "
+ this.elementCount);
if (paramInt < 0)
throw new ArrayIndexOutOfBoundsException(paramInt);
int i = this.elementCount - paramInt - 1;
if (i > 0)
System.arraycopy(this.elementData, paramInt + 1, this.elementData,
paramInt, i);
this.elementCount -= 1;
this.elementData[this.elementCount] = null;
}
synchronized 說明了這是一個線程安全的方法,刪除操作就有點複雜了,沒關係我們繼續分析:
- 第一步:它在添加元素的時候首先將modCount加1,保證線程安全。
- 第二步:第一個if判斷刪除元素是否超出了存儲的數量範圍
- 第三步:第二個if判斷待刪除的元素下標大於0
- 第四步:第三個if將元素後移
- 第五步:將數量減小1
- 第六步:將最上面的元素置爲空,也就是刪除了元素。
(4)查找操作
在上面刪除的時候我們發現了其實有一個peek()方法我們沒有將,他的作用就是返回stack中最頂端的元素。
public synchronized E peek() {
int len = size();
if (len == 0)
throw new EmptyStackException();
return elementAt(len - 1);
}
但是還有一個最正式的查找操作:
public synchronized int search(Object o) {
int i = lastIndexOf(o);
if (i >= 0) {
return size() - i;
}
return -1;
}
該方法返回所查找對象所處的位置,如果不存在在返回-1;
- 第一步:通過lastLindexOf(Object)方法返回從棧底到棧頂最下面的的那個元素的下標,
- 第二步:利用元素的總數目減去所處的下標就得到了元素的位置(),並且返回否則返回-1;
(5)其他方法
這裏提供的其他方法只有一個判斷是否爲空
public boolean empty() {
return (size() == 0);
}
以上就列出了Stack的所有源碼,超級簡單。最後我們就來對它進行有一個總結
三、總結
stack是繼承自Vector,底層使用數組存儲、用來模擬棧的一個java集合。同時也是線程安全的。使用場景比如說倒序輸出、XML語法檢查。最主要的是面試還經常使用到它,因此你主要還是在機試的時候靈活的去使用它。
就來對它進行有一個總結
三、總結
stack是繼承自Vector,底層使用數組存儲、用來模擬棧的一個java集合。同時也是線程安全的。使用場景比如說倒序輸出、XML語法檢查。最主要的是面試還經常使用到它,因此你主要還是在機試的時候靈活的去使用它。