2010-05-09 18 views
5

Tengo un problema con ArrayList. Lo necesito para almacenar un resultado. Como quiero comenzar con el elemento n, traté de dar al ArrayList una capacidad con ensureCapacity(n+1) para usar set(n,x) pero obtengo un IndexOutOfBoundsException.Java ArrayList <Double> IndexOutOfBoundsException Problema

Intenté almacenar n add(x) antes del uso del conjunto y esto funciona.

así que me gustaría saber por qué no funciona en mi camino y la forma de resolver esto porque Times n un add(x) no es un buen estilo ;-)

Respuesta

6

si no les gusta usar su propio bucle y el método de la lista add directamente a continuación, hay otra manera. Cree su ArrayList con el número de elementos que desea directamente como esto:

final int MAX_ELEMENTS = 1000; 
List<Integer> myList = new ArrayList<Integer>(
    Collections.<Integer>nCopies(MAX_ELEMENTS, null)); 

O, si ya tiene una lista que desea ampliar el tamaño de n elementos:

myList.addAll(Collections.<Integer>nCopies(n, null)); 

(Nota, supone aquí que la lista sería la celebración de Integer objetos, pero puede cambiar esto a su tipo personalizado. Si está trabajando con tipos raw/pre-Java 5, simplemente suelte las declaraciones genéricas.)

En cuanto a su pregunta real: capacidad! = Contenido. Un ArrayList internamente tiene una matriz física y un recuento de lo que realmente hay en ella. Aumentando la capacidad, cambia la matriz interna para que pueda contener tantos elementos, sin embargo, el recuento no cambia. Necesita agregar elementos para aumentar ese conteo.

Por otro lado, si usted está tratando de establecer elementos específicos y conocer el máximo que desea utilizar, por qué no utilizar una matriz directamente? Si luego necesita pasar esta matriz a una API que toma List s, entonces use Arrays.asList. Las otras clases aún podrían cambiar el contenido de su matriz de respaldo, pero no podría aumentar el tamaño o la capacidad de la misma.

7

Cuando se cambia la capacidad de una ArrayList no crea ningún elemento, solo reserva memoria donde podría haber elementos. Puede verificar el tamaño antes y después de ajustar la capacidad y verá que no cambia.

El propósito de cambiar la capacidad es saber con anticipación cuántos elementos tendrá, luego puede evitar el cambio de tamaño repetido innecesario a medida que agrega elementos nuevos, y puede evitar el desperdicio de memoria por exceso de capacidad no utilizada.

0

Usted está recibiendo esta excepción porque ensureCapacity() solamente se asegura que hay suficiente memoria asignada para añadir objetos a un ArrayList, creo que esto es en caso de que desee añadir varios objetos a la vez, sin tener que trasladarse memoria.

Para hacer lo que quiera que tendría que iniciar el ArrayList con elementos nulos primeros ...

int n = 10; //capacity required 
ArrayList foo = new ArrayList(); 

for(int i=0; i<=n; i++) { 
     foo.add(null); 
} 

entonces usted tiene objetos de la lista que puede hacer referencia a través del índice y usted no recibe la excepción.

0

ensureCapacity() tiene otro propósito. Se debe usar en casos cuando se conoce el tamaño requerido del List después de que se ha construido. Si conoce el tamaño antes de que sea el constructor, simplemente páselo como un argumento al constructor.

En el primer caso, utilice ensureCapacity() para guardar varias copias de la matriz de respaldo en cada adición. Sin embargo, usando este método deja la estructura en un estado aparentemente incompatible

  • el tamaño de la matriz de soporte se incrementa
  • el campo size en la ArrayList no lo es.

Esto, sin embargo, es normal, ya que la capacidad = tamaño

Utilice el método add(..), que es el único que está aumentando el campo size:

ArrayList list = new ArrayList(); 
list.ensureCapacity(5); // this can be done with constructing new ArrayList(5) 

for (int i = 0; i < list.size - 1; i ++) { 
    list.add(null); 
} 
list.add(yourObject); 
0

Tal vez debe reconsiderar la elección de usar List<Double>. Podría ser que un Map<Integer,Double> sería más apropiado si los elementos se agregan en un orden impar.

Si esto es apropiado depende del conocimiento sobre su uso que no tengo en este momento.

es la estructura de datos con el tiempo va a estar completamente lleno, o sea los datos dispersos?

+0

Esa sería la solución más limpia, pero ArrayList se usa como argumento en un método que solo toma ArrayList. Tal vez si tengo suficiente tiempo lo sobrecargaré por usar Map insted. –

+1

También podría considerar cargar un Mapa y luego escribir un método para construir un ArrayList a partir del contenido del mapa después de que se cargue. Pero si realmente necesita una ArrayList, la solución publicada por Bozho podría estar bien. –

+0

"ArrayList se usa como argumento en un método que solo toma ArrayList" ¿En serio? Hay un código que toma 'ArrayList' en lugar de' List'? – Powerlord

0

lo que dijeron otras personas sobre ensureCapacity() ...

debe escribir una clase como DynamicArrayList extiende ArrayList. luego simplemente anule add (n, x) para hacer con la lógica de add loop (null) especificada.

2

Como otros han respondido, ensureCapacity() está relacionado con el rendimiento, no es utilizado con frecuencia por el usuario común.

De pensamiento de Bruce Eckel en Java libro:

En un mensaje privado, Joshua Bloch escribió:" ... Creo que cometió un error al permitiendo detalles de implementación (tales como tabla hash el tamaño y el factor de carga) en nuestras API. el cliente debe quizá nos dicen el máximo esperado tamaño de una colección, y debemos tomar desde allí. los clientes pueden fácilmente hacer más daño que bien eligiendo valores para estos parámetros. Como un ejemplo extremo de , considere Vector's capacityIncrement. Nadie debería configurar esto, y no deberíamos habernos proporcionado . Si lo ajusta a cualquier valor distinto de cero , el coste asintótico de una secuencia de APPENDs va desde lineal a cuadrática. En otras palabras, destruye su rendimiento. Con el tiempo, estamos comenzando a darnos cuenta acerca de este tipo de cosas . Si nos fijamos en IdentityHashMap, podrás ver que no tiene parámetros de ajuste de bajo nivel"