2011-10-11 119 views
15

我想用Java創建堆棧,但修復了大小。例如,創建一個新的堆棧,將大小設置爲10,然後當我將物品推入堆棧時,它會填滿,當它填充到10時,堆棧中的最後一個物品被推出(移除)。我想使用Stack,因爲它使用LIFO並且非常適合我的需求。創建固定大小的堆棧

但Stack從Vector繼承的setSize()方法似乎實際上並未限制堆棧的大小。我想我錯過了Stacks的工作方式,或者Stacks不是被限制的,所以這是不可能的。請教育我!

+0

僅供參考setSize方法從Vector繼承,這意味着setSize將導致添加null以填充提供的新大小,或者丟棄超出新大小的現有對象。你可以在理論上使用這個if(stack.size()> = 10){stack.setSize(10); }每當你推入堆棧,但它會更好地實現自己的自定義類。 – Thor84no

+0

我最初試過這個只是爲了看看它是否會工作。這很奇怪,但是好像當我在堆棧上執行setSize()時,它會顛倒項目的順序並從那裏截斷它們。所以我總是最終得到原來的10個物品。同樣,另一個快速/髒的方法是(stack.size()> = 10){stack.remove(0); }同樣的問題出現在它顛倒順序的地方,所以出於某種原因,0索引是要刪除的索引。 – koopaking3

+1

這可能意味着底層的實現實際上是這樣工作的,堆棧方法以相反的順序返回給你,這無論如何都有很大的意義。 – Thor84no

回答

4

您可以創建一個非常簡單的堆棧是這樣的:

public class FixedStack<T> 
{ 
    private T[] stack; 
    private int size; 
    private int top; 

    public FixedStack<T>(int size) 
    { 
     this.stack = (T[]) new Object[size]; 
     this.top = -1; 
     this.size = size; 
    } 

    public void push(T obj) 
    { 
     if (top >= size) 
      throw new IndexOutOfBoundsException("Stack size = " + size); 
     stack[++top] = obj; 
    } 

    public T pop() 
    { 
     if (top < 0) throw new IndexOutOfBoundsException(); 
     T obj = stack[top--]; 
     stack[top + 1] = null; 
     return obj; 
    } 

    public int size() 
    { 
     return size; 
    } 

    public int elements() 
    { 
     return top + 1; 
    } 
} 
+0

我最終做了類似這樣的事情。謝謝! – koopaking3

+0

這裏有潛在的內存泄漏。 – mre

+1

@mre:好的。等一下。我會解決的。完成。這是你的意思嗎? –

0

您可以繼承Stack並重寫相應的方法來實現此自定義行爲。並確保給它一個明確的名稱(例如FixedStack)。

1

純粹的堆棧不會限制它的大小,因爲許多問題堆棧解決了你不知道你需要多少元素。

您可以編寫一個自定義堆棧來實現您描述的需求。但是,如果你這樣做,你會打破LIFO。如果滿足最大尺寸,並且您在堆疊上推新的東西,則會丟失之前添加的項目。所以如果你開始從你的堆棧中彈出物品,你會錯過一些。

1

A LinkedBlockingDeque是一個簡單的選項。使用LinkedBlockingQueue(int)構造函數,其中參數是您的堆棧限制。


如你觀察到的,和Stack模型Vector無界序列。 setSize()方法會截斷堆棧/向量。它不會阻止數據結構的增長超過這個規模。

+0

'LinkedBlockingDequeue'是一個不錯的選項(+1),但是當達到限制時它不會接受新項目。如果我正確理解OP,隊列/堆棧應該只包含最新的10個元素,所以您仍然必須實現該自動刪除。 – Thomas

+0

@Thomas - 如果使用'add'方法,您會得到異常。但是,這不符合OP的要求。 –

0

您需要的是像LinkedList這樣的雙端隊列。雖然這不會自動刪除前面的元素,但通過繼承/裝飾它,您可以添加該功能。

1

這不是不可能:)你只需要提供你自己的實現。

我會從this這樣的RingBuffer開始,並相應地進行調整。

0

您可以使用LinkedHashMap的並覆蓋其removeEldestEntry方法:

public class FixedStack extends LinkedHashMap<Long, String> { 

    private final int capacity; 

    public FixedStack(int capacity) { 
     this.capacity = capacity; 
    } 

    @Override 
    protected boolean removeEldestEntry(final Map.Entry<Long, String> eldest) { 
     return super.size() > capacity; 
    } 
} 

,並測試它:

public static void main(String[] args) { 

     FixedStack stack = new FixedStack(10); 

     long added = 0; 
     for (Locale locale : Locale.getAvailableLocales()) { 
      if (locale.getDisplayCountry().length() > 0) { 
       stack.put(added, locale.getDisplayCountry()); 
       System.out.println(locale.getDisplayCountry()); 
       added++; 
      } 
     } 
     System.out.println(String.format(">>>>>>>>> %s added", 
       added)); 
     Iterator<Entry<Long, String>> iterator = stack.entrySet().iterator(); 
     while (iterator.hasNext()) { 
      System.out.println(iterator.next().getValue()); 
     } 
    } 

你只需要決定你想用什麼作爲關鍵,我在示例中使用了一個簡單的計數器。

19

這裏是一個SizedStack類型擴展Stack

import java.util.Stack; 

public class SizedStack<T> extends Stack<T> { 
    private int maxSize; 

    public SizedStack(int size) { 
     super(); 
     this.maxSize = size; 
    } 

    @Override 
    public T push(T object) { 
     //If the stack is too big, remove elements until it's the right size. 
     while (this.size() >= maxSize) { 
      this.remove(0); 
     } 
     return super.push(object); 
    } 
} 

使用方法如下:SizedStack<Float> mySizedStack = new SizedStack<Float>(10);。除了尺寸之外,它與其他Stack一樣運作。

+1

這太棒了!我會建議用'if(this.size()== maxSize)'替換'while(this.size()> maxSize)',以便初始化'SizedStack'的大小將是實際允許的最大大小疊加。 –

+1

我把它改成'while(this.size()> = maxSize)'來照顧你注意到的錯誤的錯誤。謝謝。儘管如此,它仍然應該是一個安全循環的while循環;如果尺寸大於maxSize,會發生什麼?我知道這似乎不可能,但錯誤是錯誤:)。 – Calvin

+1

我喜歡備份您的選擇的體貼!好電話:D –