我想用Java創建堆棧,但修復了大小。例如,創建一個新的堆棧,將大小設置爲10,然後當我將物品推入堆棧時,它會填滿,當它填充到10時,堆棧中的最後一個物品被推出(移除)。我想使用Stack,因爲它使用LIFO並且非常適合我的需求。創建固定大小的堆棧
但Stack從Vector繼承的setSize()方法似乎實際上並未限制堆棧的大小。我想我錯過了Stacks的工作方式,或者Stacks不是被限制的,所以這是不可能的。請教育我!
我想用Java創建堆棧,但修復了大小。例如,創建一個新的堆棧,將大小設置爲10,然後當我將物品推入堆棧時,它會填滿,當它填充到10時,堆棧中的最後一個物品被推出(移除)。我想使用Stack,因爲它使用LIFO並且非常適合我的需求。創建固定大小的堆棧
但Stack從Vector繼承的setSize()方法似乎實際上並未限制堆棧的大小。我想我錯過了Stacks的工作方式,或者Stacks不是被限制的,所以這是不可能的。請教育我!
您可以創建一個非常簡單的堆棧是這樣的:
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;
}
}
您可以繼承Stack
並重寫相應的方法來實現此自定義行爲。並確保給它一個明確的名稱(例如FixedStack
)。
純粹的堆棧不會限制它的大小,因爲許多問題堆棧解決了你不知道你需要多少元素。
您可以編寫一個自定義堆棧來實現您描述的需求。但是,如果你這樣做,你會打破LIFO。如果滿足最大尺寸,並且您在堆疊上推新的東西,則會丟失之前添加的項目。所以如果你開始從你的堆棧中彈出物品,你會錯過一些。
A LinkedBlockingDeque
是一個簡單的選項。使用LinkedBlockingQueue(int)
構造函數,其中參數是您的堆棧限制。
如你觀察到的,和Stack
模型Vector
無界序列。 setSize()
方法會截斷堆棧/向量。它不會阻止數據結構的增長超過這個規模。
'LinkedBlockingDequeue'是一個不錯的選項(+1),但是當達到限制時它不會接受新項目。如果我正確理解OP,隊列/堆棧應該只包含最新的10個元素,所以您仍然必須實現該自動刪除。 – Thomas
@Thomas - 如果使用'add'方法,您會得到異常。但是,這不符合OP的要求。 –
您需要的是像LinkedList
這樣的雙端隊列。雖然這不會自動刪除前面的元素,但通過繼承/裝飾它,您可以添加該功能。
這不是不可能:)你只需要提供你自己的實現。
我會從this這樣的RingBuffer開始,並相應地進行調整。
您可以使用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());
}
}
你只需要決定你想用什麼作爲關鍵,我在示例中使用了一個簡單的計數器。
這裏是一個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
一樣運作。
這太棒了!我會建議用'if(this.size()== maxSize)'替換'while(this.size()> maxSize)',以便初始化'SizedStack'的大小將是實際允許的最大大小疊加。 –
我把它改成'while(this.size()> = maxSize)'來照顧你注意到的錯誤的錯誤。謝謝。儘管如此,它仍然應該是一個安全循環的while循環;如果尺寸大於maxSize,會發生什麼?我知道這似乎不可能,但錯誤是錯誤:)。 – Calvin
我喜歡備份您的選擇的體貼!好電話:D –
僅供參考setSize方法從Vector繼承,這意味着setSize將導致添加null以填充提供的新大小,或者丟棄超出新大小的現有對象。你可以在理論上使用這個if(stack.size()> = 10){stack.setSize(10); }每當你推入堆棧,但它會更好地實現自己的自定義類。 – Thor84no
我最初試過這個只是爲了看看它是否會工作。這很奇怪,但是好像當我在堆棧上執行setSize()時,它會顛倒項目的順序並從那裏截斷它們。所以我總是最終得到原來的10個物品。同樣,另一個快速/髒的方法是(stack.size()> = 10){stack.remove(0); }同樣的問題出現在它顛倒順序的地方,所以出於某種原因,0索引是要刪除的索引。 – koopaking3
這可能意味着底層的實現實際上是這樣工作的,堆棧方法以相反的順序返回給你,這無論如何都有很大的意義。 – Thor84no