2011-10-11 24 views
15

Quiero crear una pila en Java, pero repare el tamaño. Por ejemplo, cree una nueva pila, establezca el tamaño en 10, luego, cuando coloque elementos en la pila, se llene y cuando se llene hasta diez, el último elemento de la pila se empujará (se eliminará). Quiero usar Stack porque usa LIFO y se adapta muy bien a mis necesidades.Crear una pila de tamaño fijo

Pero el método setSize() que Stack hereda de Vector no parece limitar realmente el tamaño de la pila. Creo que me falta algo acerca de cómo funcionan las pilas, o quizás las pilas no estaban destinadas a ser restringidas por lo que es imposible. ¡Por favor, enséñame!

+0

FYI el método setSize se hereda de Vector, lo que significa que setSize hará que los nulos se agreguen para llenar el nuevo tamaño provisto, o los objetos existentes más allá del nuevo tamaño se descartan. En teoría, podría usar esto haciendo if (stack.size()> = 10) {stack.setSize (10); } cada vez que empuja hacia la pila, pero sería mejor implementar su propia Clase personalizada. – Thor84no

+0

Intenté esto originalmente solo para ver si funcionaría. Es extraño, pero parece que cuando hago el setSize() en la pila, invierte el orden de los elementos y los trunca desde allí. Así que siempre termino con los 10 elementos originales en la pila. Del mismo modo, otra forma rápida/sucia de hacerlo es (stack.size()> = 10) {stack.remove (0); } El mismo problema surge cuando invierte el orden, por lo que por alguna razón el índice 0 es el que debe eliminarse. – koopaking3

+1

Eso probablemente solo signifique que la implementación subyacente realmente funciona de esa manera y los métodos de pila te devuelven las cosas en orden inverso, lo que tiene mucho sentido de todos modos. – Thor84no

Respuesta

4

Puede crear una pila muy simple como esto:

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

Terminé haciendo algo parecido a esto. ¡Gracias! – koopaking3

+0

Aquí hay un potencial para una pérdida de memoria. – mre

+1

@mre: Ok. Espere. Voy a arreglar. Hecho. ¿Es esto lo que querías decir? –

0

Puede crear la subclase Stack y anular los métodos apropiados para implementar este comportamiento personalizado. Y asegúrese de darle un nombre claro (por ejemplo, FixedStack).

1

Una pila pura no limitaría su tamaño, ya que muchos de los problemas que resuelven las pilas no saben cuántos elementos va a necesitar.

Puede escribir una pila personalizada que implemente las necesidades que describió. Sin embargo, romperás LIFO si lo haces. Si se alcanza el tamaño máximo y empuja algo nuevo en la pila, solo pierde el elemento agregado anteriormente. Entonces, si luego comienzas a sacar elementos de tu pila, te perderás algunos.

1

A LinkedBlockingDeque es una opción simple. Use el constructor LinkedBlockingQueue(int) donde el parámetro es el límite de su pila. secuencias sin límites


Como usted observó, Stack y Vector modelo. El método setSize() trunca la pila/vector. No impide que la estructura de datos crezca más allá de ese tamaño.

+0

'LinkedBlockingDequeue' es una buena opción (+1), sin embargo, simplemente no aceptará nuevos elementos cuando se alcance el límite. Si entiendo el OP correctamente, la cola/pila solo debería contener los 10 elementos más nuevos, por lo que aún tendría que implementar esa caída automática. – Thomas

+0

@Thomas - si usa los métodos 'add' obtendrá una excepción en su lugar. Pero sí, esto no coincide exactamente con los requisitos del OP. –

0

Lo que necesita es una cola de doble terminación como LinkedList. Sin embargo, esto no soltaría elementos automáticamente en el frente, pero al subclasar/decorarlo podría agregar esa funcionalidad.

1

Esto no es imposible :) Solo tiene que proporcionar su propia implementación.

Comenzaría con un RingBuffer como this y lo ajustaría en consecuencia.

0

Puede utilizar LinkedHashMap y anular su método 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; 
    } 
} 

Y para probarlo:

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()); 
     } 
    } 

Solo tienes que decidir qué quieres usar como clave, utilicé un contador simple en el ejemplo.

19

Aquí es un tipo SizedStack que se extiende 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); 
    } 
} 

utilizar de esta manera: SizedStack<Float> mySizedStack = new SizedStack<Float>(10);. Aparte del tamaño, funciona como cualquier otro Stack.

+1

¡Esto es genial! Sugeriría reemplazar 'while (this.size()> maxSize)' con 'if (this.size() == maxSize)' para que el tamaño inicialice 'SizedStack' sea el tamaño máximo real permitido para el apilar. –

+1

Lo cambié a 'while (this.size()> = maxSize)' para encargarme del error "uno por uno" que notó. Gracias. Sin embargo, debería ser un ciclo while por motivos de seguridad; ¿Qué pasaría si el tamaño de alguna manera fuera más grande que MaxSize? Sé que parece imposible, pero los errores son errores :). – Calvin

+1

¡Me gusta la reflexión que respalda tu elección! Buena llamada: D –

Cuestiones relacionadas