標籤:java 資料結構 源碼
歡迎轉載,請附出處:
http://blog.csdn.net/as02446418/article/details/47123581
1.簡介
棧是資料結構中一種很重要的資料結構類型,因為棧的後進先出功能是實際的開發中有很多的應用情境。Java API中提供了棧(Stacck)的實現,簡單使用如下所示
import java.util.Stack;public class StackTest { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Stack<String> stack = new Stack<String>(); stack.add("China"); stack.add("Japan"); stack.add("Russia"); stack.add("England"); System.out.println(stack.size()+"<="+stack.capacity()); System.out.println(stack.elementAt(0)); System.out.println(stack.get(0)); System.out.println(stack.peek()); System.out.println(stack.push("France")); System.out.println(stack.pop()); System.out.println(stack.iterator()); System.out.println(stack.empty()); System.out.println(stack.isEmpty()); System.out.println(stack.search("Russia")); }}
2.繼承結構
Stack類繼承了Vector類,而Vector類繼承了AbstractList抽象類別,實現了List介面,Cloneable介面,RandomAcces介面以及Serializable介面,需要指出的Vector內部還有兩個內部類ListItr和Itr,Itr在繼承Vector的同時實現了Iterator介面,而ListItr在繼承了Itr類的同時實現了ListIterator介面。
3.源碼解讀
通過Stack類發現含有的方法有pop(),peek(),push(Object),search(Object),empty()方法,其他值的方法是從Vector類繼承而來,通過源碼可以發現Vector有幾個屬性值: protected Object[] elementData , protected int elementCount ; protected int capacityIncrement ; private static final int MAX_ARRAY_SIZE = 2147483639; 通過這幾屬性我們可以發現,Stack底層是採用數組來實現的,elementData用於儲存Stack中的每個元素;elementCount用於動態儲存元素的個數,capacityIncrement用來儲存Stack的容量(一般情況下應該是大於elementCount);MAX_ARRAY_SIZE 用於限制Stack能夠儲存的最大值數量。
a.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; }
removeElementAt()方法用於移除某個位置的元素,需要指出元素的位置,這個方法來之與Stack的父類Vector;通過代碼我們可以發現它的實現是首先判斷參數是否合法然後將這個位置前的所有元素都向後移動了一位,而且把元素的個數-1,最後把原來位置最上面的那個元素置為空白,從而實現了刪除某個元素的操作。
b:elementData(int)
E elementData(int paramInt) { return this.elementData[paramInt]; }
elementData(int)返回某一位置的元素的具體值,通過這個方面也可以看出Stack底層是有一個數組來實現的 。
c:elementAt(int)
public synchronized E elementAt(int paramInt) { if (paramInt >= this.elementCount) throw new ArrayIndexOutOfBoundsException(paramInt + " >= " + this.elementCount); return elementData(paramInt); }elementAt(int paramInt)首先判斷參數是否合法,然後就直接調用elementData(paramInt)返回具體的對象值。
d:peek()
public synchronized E peek() { int i = size(); if (i == 0) throw new EmptyStackException(); return elementAt(i - 1); }
通過源碼就可以發現peek()只是擷取了第一個位置的元素的值(Stack的下標和數組保持一致都是從0開始,最大到元素總數-1)
e:pop()
public synchronized E pop() { int i = size(); Object localObject = peek(); removeElementAt(i - 1); return localObject; }
pop()方法的實現是首先擷取Stack的元素數量,然後調用peek()方法擷取棧頂的第一個元素,然後調用removeElementAt(int)刪除棧頂元素,最後將元素的值返回。
f:addElement(E paramE)
public synchronized void addElement(E paramE) { this.modCount += 1; ensureCapacityHelper(this.elementCount + 1); this.elementData[(this.elementCount++)] = paramE; }
addElement(E)方法是個很重要的方法,因為它實現了元素的添加。它在添加元素的時候首先將modCount加1,ensureCapacityHelper()主要用於保障Stack的容量,如果超過當前容量則調用grow()方法進行容量增加,如果操作最大的容量MAX_ARRAY_SIZE就會拋出異常。第三步才會實現元素的添加,就是i將該元素添加到棧頂,並且將元素的數目加1;
g:search(Object)
public synchronized int search(Object paramObject) { int i = lastIndexOf(paramObject); if (i >= 0) return (size() - i); return -1; }
該方法返回所尋找對象所處的位置,如果不存在在返回-1;通過代碼可以發現它的實現過程是這樣的,首先通過lastLindexOf(Object)方法返回從棧底到棧頂最下面的的那個元素的下標,然後利用元素的總數目減去所處的下標就得到了元素的位置(),並且返回否則返回-1;(需要注意的改位置返回的是從棧頂到棧底開始所處的位置,棧頂元素的位置為1)
h:empty()public boolean empty() { return (size() == 0); }
直接返回元素的數目與0比較的關係,size()方法是通過this.elementCount返回了棧元素的數目。
4.其他(小結)
通過源碼我們可以看到Vector底層是一個數組,說明Stack的實現是通過數組來實現的,然後通過對數組的操作來模仿棧的各種功能。而且在源碼中Vector的很多方法都是synchronized 的,也就是說是安全執行緒,所以說在多線程中是可以安全使用的,不過這樣效率上肯定是會降低的。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Java集合之Stack 源碼分析