為什么 java.util.Stack不被官方所推薦使用!


Java 為什么不推薦使用 Stack 呢?

  因為 Stack 是 JDK 1.0 的產物。它繼承自 Vector,Vector 都不被推薦使用了,你說 Stack 還會被推薦嗎?

  當初 JDK1.0 在開發時,可能為了快速的推出一些基本的數據結構操作,所以推出了一些比較粗糙的類。比如,Vector、Stack、Hashtable等。這些類中的一些方法加上了 synchronized 關鍵字,容易給一些初級程序員在使用上造成一些誤解!而且在之前的幾個版本中,性能還不怎么好。

  基於 Vector 實現的棧 Stack。底層實際上還是數組,所以還是存在需要擴容。Vector 是由數組實現的集合類,它包含了大量集合處理的方法。而 Stack 之所以繼承 Vector,是為了復用 Vector 中的方法,來實現進棧(push)、出棧(pop)等操作。這里就是 Stack 設計不好的地方,既然只是為了實現棧,不用鏈表來單獨實現,而是為了復用簡單的方法而迫使它繼承 Vector,Stack 和 Vector 本來是毫無關系的。這使得 Stack 在基於數組實現上效率受影響,另外因為繼承 Vector 類,Stack 可以復用 Vector 大量方法,這使得 Stack 在設計上不嚴謹。

  Java 提供了 Deuqe。Deque 是繼承自 Queue,而 Stack 是繼承自 Vector。Java 中的 Deuqe,即“double ended queue”的縮寫,是 Java 中的雙端隊列集合類型。Deque 具備普通隊列 FIFO 的功能,同時它也具備了 Stack 的 LIFO 功能,並且保留了 push 和 pop 函數,所以使用起來應該是一點障礙都沒有。

  ArrayDeque 是 Deque 接口的一種具體實現,是依賴於可變數組來實現的。ArrayDeque 沒有容量限制,可根據需求自動進行擴容。ArrayDeque 可以作為棧來使用,效率要高於 Stack。ArrayDeque 也可以作為隊列來使用,效率相較於基於雙向鏈表的 LinkedList 也要更好一些。注意,ArrayDeque 不支持為 null 的元素。

原文鏈接:https://www.xttblog.com/?p=3416

關於java.util.stack的底層實現

當push一個元素時:

public E push(E item) {
    addElement(item);
    return item;
}

實際上調用但是Vector的addElement方法

public synchronized void addElement(E obj) {
    modCount++;
    ensureCapacityHelper(elementCount + 1);
    elementData[elementCount++] = obj;
}

而Vector的底層實現就是一個數組,初始大小為10,每當元素超出就增長為原來的2倍,和ArrayList的增長方式類似。

public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
    protected Object[] elementData;
    public Vector() {
      //初始大小為10
    this(10);
    }
    public Vector(int initialCapacity) {
    this(initialCapacity, 0);
    }
    public Vector(int initialCapacity, int capacityIncrement) {
    super();
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
        //初始化為10
    this.elementData = new Object[initialCapacity];
    this.capacityIncrement = capacityIncrement;
	……
 }

  總結:在java.util.stack中,棧的底層是使用數組來實現的,數組初始大小為10。每當元素個數超出數組容量就擴展為原來的2倍,將原數組中的元素拷貝到新數組中,隨着數組元素的增多,這種開銷也越大。
​ Java並不推薦使用java.util.stack來進行棧的操作,而是推薦使用一個雙端隊列“deque ”來代替它。

關於“deque”

public interface Deque<E>extends Queue<E>

  它是一個線性 collection,支持在兩端插入和移除元素。名稱 deque 是“double ended queue(雙端隊列)”的縮寫,通常讀為“deck”。大多數 Deque 實現對於它們能夠包含的元素數沒有固定限制,但此接口既支持有容量限制的雙端隊列,也支持沒有固定大小限制的雙端隊列。

  此接口定義在雙端隊列兩端訪問元素的方法。提供插入、移除和檢查元素的方法。每種方法都存在兩種形式:一種形式在操作失敗時拋出異常,另一種形式返回一個特殊值(null 或 false,具體取決於操作)。插入操作的后一種形式是專為使用有容量限制的 Deque 實現設計的;在大多數實現中,插入操作不能失敗。
  雙端隊列也可用作 LIFO(后進先出)堆棧。應優先使用此接口而不是遺留 Stack 類。在將雙端隊列用作堆棧時,元素被推入雙端隊列的開頭並從雙端隊列開頭彈出。堆棧方法完全等效於 Deque 方法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM