2011-03-05 63 views
32

¿Es posible definir una lista con un tamaño fijo de 100? Si no, ¿por qué no está disponible en Java?Defina una lista de tamaño fijo en Java

+1

Puede establecer el tamaño inicial de una ArrayList, pero si agrega más elementos se expandirá a sí mismo –

+5

fijo o máximo? ¿Desea que la lista no tenga más de 100 elementos? ¿Y qué debería suceder si se intenta 'add()'? Excepción, nada o un elemento existente descartado a favor del nuevo. – Bozho

+7

¿No son estas bestias llamadas "matrices"? –

Respuesta

14

,

Commons library proporciona un tamaño incorporado FixedSizeList que no soporta los métodos add, remove y clear (pero se permite que el método set, ya que no modifica el List 's) En otras palabras, si intenta llamar a uno de estos métodos, su lista aún conservará el mismo tamaño.

para crear su lista de tamaño fijo, simplemente llame

List<YourType> fixed = FixedSizeList.decorate(Arrays.asList(new YourType[100])); 
+9

¿Por qué decorará el resultado de Arrays.asList si ya es una lista de tamaño fijo? – PhoneixS

+3

Sí ... el 'FixedSizeList.decorate (...)' es para envolver listas que aún no tienen un tamaño fijo. Usarlo aquí es redundante. –

27

Esto debe hacerlo si falla la memoria:

List<MyType> fixed = Arrays.asList(new MyType[100]); 
+0

¿mantendrá el tamaño en 100 si continúa agregando? – fastcodejava

+3

arrojará una excepción – Bozho

+7

@fastcodejava - no puede usar el método 'add' con una lista de longitud fija; ya tiene 100 entradas nulas. Use 'set' para establecer valores. – McDowell

3

crear una matriz de tamaño 100. Si necesita la interfaz de lista, a continuación, llamar Arrays.asList en él. Devolverá una lista de tamaño fijo respaldada por la matriz.

+0

Votación negativa inexplicada votada. La respuesta es correcta. @Downvoter por favor explique, de lo contrario, nadie aprende nada, excepto que en este caso está equivocado. – EJP

11

Sí. Puede pasar una matriz de Java al Arrays.asList(Object[]).

List<String> fixedSizeList = Arrays.asList(new String[100]); 

No puede insertar cadenas nuevas en fixedSizeList (ya tiene 100 elementos). Solo puede establecer sus valores de esta manera:

fixedSizeList.set(7, "new value"); 

De esta manera usted tiene una lista de tamaños fijos. La cosa funciona como una matriz y no puedo pensar en una buena razón para usarla. Me encantaría saber por qué quieres que tu colección de tamaño fijo sea una lista en lugar de simplemente usar una matriz.

+0

las matrices no pueden ser geneificadas. –

+0

Mi razón es la misma que la de Jeffrey. Impresionado al saber que no puede tener la línea: T [] myGenericArray = new T [5]; – Swiftslide

+1

Esto es perfecto. En lugar de "Cadena" tenemos que poner la clase de Objeto según el requisito. Gracias. – Debarati

2

Si desea cierta flexibilidad, cree una clase que mire el tamaño de la lista.

Aquí hay un ejemplo simple. Tendrá que anular todos los métodos que cambian el estado de la lista.

public class LimitedArrayList<T> extends ArrayList<T>{ 
    private int limit; 

    public LimitedArrayList(int limit){ 
     this.limit = limit; 
    } 

    @Override 
    public void add(T item){ 
     if (this.size() > limit) 
      throw new ListTooLargeException(); 
     super.add(item); 
    } 

    // ... similarly for other methods that may add new elements ... 
+1

El método add (int index, T element) también deberá sobrescribirse. – shams

+0

@shams: Es por eso que dije "necesitarías anular todos los métodos que cambian el estado de la lista" ... – Jeremy

+0

Sí, creo que manejar estos dos debería ser suficiente. Los add * son los únicos métodos de la interfaz estándar que pueden aumentar el tamaño de la lista. Creo que hay cuatro de ellos, pero los otros dos (addAll *) a su vez llaman a los métodos add *. – shams

25

Puede ser que su pregunta de manera inadecuada, o si tiene un modelo mental errónea de lo que es un Java List.


Una lista de Java es una colección de objetos ... los elementos de una lista. El tamaño de la lista es la cantidad de elementos en esa lista. Si desea que se corrija ese tamaño, eso significa que no puede agregar o eliminar elementos, ya que agregar o quitar elementos violaría su restricción de "tamaño fijo".

La forma más sencilla de implementar una lista de "tamaño fijo" (¡si eso es realmente lo que quiere!) Es poner los elementos en una matriz y luego Arrays.asList(array) para crear la envoltura de la lista. El contenedor le permitirá realizar operaciones como get y set, pero las operaciones add y remove generarán excepciones.

Y si desea crear un contenedor de tamaño fijo para una lista existente, entonces podría utilizar la clase Apache commons FixedSizeList. Pero tenga en cuenta que este contenedor no puede evitar que otra cosa cambie el tamaño de la lista original, y si eso sucede, la lista envolvente presumiblemente reflejará esos cambios. (IMO, el javadoc para FixedSizeList es lamentable. No intenta documentar cómo se comporta la clase cuando se modifica la lista envuelta. Deberá leer el código fuente ... y esperar que no cambien el comportamiento cuando no están prestando atención.)


por otro lado, si realmente desea un tipo de lista con un límite fijo (o límites) de su tamaño, entonces usted necesita para crear su propia clase List para implementar esta. Por ejemplo, puede crear una clase contenedora que implemente las comprobaciones relevantes en las diversas operaciones add/addAll y remove/removeAll/retainAll. (Y en el iterador remove métodos si son compatibles.)

¿Por qué el framework de colecciones de Java no implementa esto? He aquí por qué creo que sí:

  1. Los casos de uso que lo necesitan son raros.
  2. Los casos de uso donde esto es necesario, existen diferentes requisitos sobre qué hacer cuando una operación intenta romper los límites; p.ej. lanzar excepción, ignorar operación, descartar algún otro elemento para hacer espacio.
  3. Una implementación de lista con límites podría ser problemática para los métodos de ayuda; p.ej. Collections.sort.
+0

Buen comentario, pero el java oficial recomienda ahora usar el arraylist en lugar del array cuando sea posible, por lo que muchos programadores harán esta pregunta en el futuro. Estoy hablando, por ejemplo, sobre el libro oficial para el programador java se 7. – arisalexis

+0

@arisalexis - 1) ¿De qué libro estás hablando? Proporcione el título/autor preciso ... o una URL. 2) ¿Lo que el libro * contradice * es lo que estoy diciendo? ¿O solo está agregando un hecho (IMO: en gran medida no relacionado)? –

+0

No estoy contradiciendo su publicación, solo estoy señalando algo que no parecía estar relacionado conmigo. Al tomar el examen OCA java 7 y leer el libro del oráculo escrito por edward Finegan y Robert Ligiguori se afirma que "en la mayoría de los casos el método preferido para almacenar datos en una matriz es mediante listas ". Solo digo que a veces las personas aprenden a usar listas de arreglos para todo y luego llegan a estas preguntas. – arisalexis

8

Normalmente una alternativa para el tamaño fijo Las listas son matrices de Java. Las listas de forma predeterminada pueden crecer/contraerse en Java. Sin embargo, eso no significa que no puedas tener una lista de un tamaño fijo. Tendrá que hacer un trabajo y crear una implementación personalizada.

Puede extender un ArrayList con implementaciones personalizadas de los métodos borrar, agregar y eliminar.

p. Ej.

import java.util.ArrayList; 

public class FixedSizeList<T> extends ArrayList<T> { 

    public FixedSizeList(int capacity) { 
     super(capacity); 
     for (int i = 0; i < capacity; i++) { 
      super.add(null); 
     } 
    } 

    public FixedSizeList(T[] initialElements) { 
     super(initialElements.length); 
     for (T loopElement : initialElements) { 
      super.add(loopElement); 
     } 
    } 

    @Override 
    public void clear() { 
     throw new UnsupportedOperationException("Elements may not be cleared from a fixed size List."); 
    } 

    @Override 
    public boolean add(T o) { 
     throw new UnsupportedOperationException("Elements may not be added to a fixed size List, use set() instead."); 
    } 

    @Override 
    public void add(int index, T element) { 
     throw new UnsupportedOperationException("Elements may not be added to a fixed size List, use set() instead."); 
    } 

    @Override 
    public T remove(int index) { 
     throw new UnsupportedOperationException("Elements may not be removed from a fixed size List."); 
    } 

    @Override 
    public boolean remove(Object o) { 
     throw new UnsupportedOperationException("Elements may not be removed from a fixed size List."); 
    } 

    @Override 
    protected void removeRange(int fromIndex, int toIndex) { 
     throw new UnsupportedOperationException("Elements may not be removed from a fixed size List."); 
    } 
} 
0

Si desea utilizar ArrayList o LinkedList, parece que la respuesta es no. Aunque hay algunas clases en Java que pueden establecerse en tamaño fijo, como PriorityQueue, ArrayList y LinkedList no pueden, porque no hay ningún constructor para que estas dos especifiquen capacidad.

Si desea adherirse a ArrayList/LinkedList, una solución fácil es verificar el tamaño manualmente cada vez.

public void fixedAdd(List<Integer> list, int val, int size) { 
    list.add(val); 
    if(list.size() > size) list.remove(0); 
} 

LinkedList es mejor que ArrayList en esta situación. Supongamos que hay muchos valores para agregar pero el tamaño de la lista es bastante simple, habrá muchas operaciones de eliminación. La razón es que el costo de eliminar de ArrayList es O (N), pero solo O (1) para LinkedList.

Cuestiones relacionadas