Tamaño inicial de ArrayList

257

Puede establecer el tamaño inicial de una ArrayList haciendo

ArrayList<Integer> arr=new ArrayList<Integer>(10);

Sin embargo, no puedes hacer

arr.add(5, 10);

porque causa una excepción fuera de límites.

¿De qué sirve establecer un tamaño inicial si no puede acceder al espacio que asignó?

La función de agregar se define add(int index, Object element)así que no estoy agregando al índice 10.

Cemre
fuente
52
En realidad, no es obvio de los documentos que una lista necesita tener al menos n elementos agregados antes de que pueda agregar el set/addelemento n-1 .
Percepción el
55
Percepción: no sé si es obvio, pero está especificado. Uno tiene que leer JavaDoc cuidadosamente. Lanza: IndexOutOfBoundsException - si el índice está fuera de rango (index <0 || index> = size ()).
Natix
3
Hm, el constructor dice "Construye una lista vacía con la capacidad inicial especificada", tomando la noción de una lista vacía, no puede haber un índice 5. Pero estoy de acuerdo en que esto podría no ser visible a primera vista ...
quaylar
12
Creo que también es justo decir que si inicializa una matriz a un valor específico, asumirá que los índices inferiores a ese valor están disponibles, y esto es un ArrayList. Personalmente, me gustaría un método que me permitiera establecer un tamaño tal que pudiera poner las cosas en índices específicos. Este método parece notablemente ausente.
Andrew Wyld
1
¿Qué numbskull diseñó las colecciones de esta manera? Esto fuerza el trabajo redundante para la creación de instancias paralelas de una estructura con elementos de longitud variable (es decir, ArrayList <String []> donde cada matriz puede tener una longitud diferente). Si la memoria ya está asignada, por lo que la lista no necesita reasignación después de agregar N elementos, esos índices deberían ser directamente accesibles desde el principio. ¿Nadie en Oracle aprendió este patrón después de C / C ++, C #, Objective C y Swift?
patrickjp93

Respuestas:

387

Estás confundiendo el tamaño de la lista de matriz con su capacidad:

  • el tamaño es el número de elementos en la lista;
  • la capacidad es la cantidad de elementos que la lista puede acomodar potencialmente sin reasignar sus estructuras internas.

Cuando llama new ArrayList<Integer>(10), está configurando la capacidad inicial de la lista , no su tamaño. En otras palabras, cuando se construye de esta manera, la lista de matriz comienza su vida vacía.

Una forma de agregar diez elementos a la lista de la matriz es mediante un bucle:

for (int i = 0; i < 10; i++) {
  arr.add(0);
}

Una vez hecho esto, ahora puede modificar elementos en los índices 0..9.

NPE
fuente
51
+1: Un ciclo más corto es while(arr.size() < 10) arr.add(0);Puede ser útil decir que el tamaño debe ser al menos 10. por ejemplo, para que pueda usarloarr.set(9, n);
Peter Lawrey
10
+1: Gran respuesta, daría +10 si pudiera. No es inmediatamente obvio a partir de la API por qué no puede establecer AMBOS el tamaño inicial y la capacidad inicial en una sola llamada de constructor. Tienes que leer la API y decir "Oh, supongo que ArrayList no tiene un método o un constructor para hacerlo"
demongolem
@PeterLawrey Su código puede ser más corto, pero contiene dos llamadas de método por iteración de bucle, en lugar de solo una.
Neuralmer
@neuralmer Esperaría que size () y add () estén en línea para que no se produzca una llamada al método real en tiempo de ejecución.
Peter Lawrey
109

Si desea una lista con un tamaño predefinido, también puede usar:

List<Integer> arr = Arrays.asList(new Integer[10]);
Gert Jan Schoneveld
fuente
11
Ligera desventaja aquí, el resultado Listestá lleno de nulos. Con Guava podemos hacer Ints.asList(new int[10])lo que inicializará nuestra lista con 0s. Sin embargo, patrón limpio, gracias por el ejemplo.
dimo414
1
Las preguntas hablan sobre ArrayList <E>. Estás utilizando la Lista <E>. ¿Nadie ha observado esto? Además, ¡han votado esta respuesta irrelevante ! No rechazo tu respuesta porque nunca lo hago. Simplemente ... ¡Dios santo!
Apostolos
3
@Apostolos ArrayListes una implementación de la Listinterfaz y Arrays.asListdevuelve un ArrayList. Te sugiero que busques polimorfismo.
Liam Potter
Sin embargo, esto devuelve una Lista con un tamaño fijo. Tratando de agregar más elementos lanzamientosUnsupportedOperationException
Koray Tugay
47

si desea usar Collections.fill (list, obj); para llenar la lista con un objeto repetido, alternativamente, puede usar

ArrayList<Integer> arr=new ArrayList<Integer>(Collections.nCopies(10, 0));

la línea copia 10 veces 0 en su ArrayList

Farzan Skt
fuente
20

La capacidad de un ArrayListno es lo mismo que su tamaño . El tamaño es igual al número de elementos contenidos en ArrayList(y cualquier otra Listimplementación).

La capacidad es solo la longitud de la matriz subyacente que se utiliza para almacenar internamente los elementos de la ArrayList, y siempre es mayor o igual al tamaño de la lista.

Al llamar set(index, element)a la lista, se indexrelaciona con el número real de los elementos de la lista (= tamaño) (que es cero en su código, por lo tanto, AIOOBEse arroja), no con la longitud de la matriz (= capacidad) (que es un detalle de implementación específico a la ArrayList).

El setmétodo es común a todas las Listimplementaciones, como por ejemplo LinkedList, que no está implementado realmente por una matriz, sino como una cadena vinculada de entradas.

Editar : en realidad usas el add(index, element)método, no set(index, element), pero el principio es el mismo aquí.

Natix
fuente
10

Si desea agregar los elementos con índice, en su lugar podría usar una matriz.

    String [] test = new String[length];
    test[0] = "add";
usuario3692587
fuente
55
OP quería usar una Lista inicialmente ... no una matriz.
Stephan
9

10 es la capacidad inicial de la AL, no el tamaño (que es 0). Debe mencionar la capacidad inicial a un valor alto cuando va a tener muchos elementos, ya que evita la sobrecarga de expandir la capacidad a medida que continúa agregando elementos.

Bhesh Gurung
fuente
6

Supongo que una respuesta exacta a tu pregunta sería:

Establecer un tamaño inicial en una ArrayList reduce el nr. de veces la reasignación de memoria interna tiene que ocurrir. La lista está respaldada por una matriz. Si especifica, es decir, la capacidad inicial 0, ya en la primera inserción de un elemento, la matriz interna debería ser redimensionada. Si tiene una idea aproximada de cuántos elementos contendrá su lista, establecer la capacidad inicial reduciría el nr. de reasignaciones de memoria que suceden mientras usa la lista.

muelle
fuente
3

Esto podría ayudar a alguien

ArrayList<Integer> integerArrayList = new ArrayList<>(Arrays.asList(new Integer[10]));
Hrishikesh Kadam
fuente
3

Llegar tarde a esto, pero después de Java 8 , personalmente considero que este siguiente enfoque con la StreamAPI es más conciso y puede ser una alternativa a la respuesta aceptada .

Por ejemplo,

Arrays.stream(new int[size]).boxed().collect(Collectors.toList())

donde sizees el Listtamaño deseado y sin la desventaja mencionada aquí , todos los elementos en el Listse inicializan como0 .

(Hice una búsqueda rápida y no vi streamninguna respuesta publicada; no dude en informarme si esta respuesta es redundante y puedo eliminarla)

HT Koo
fuente
1

En este momento no hay elementos en su lista, por lo que no puede agregar al índice 5 de la lista cuando no existe. Está confundiendo la capacidad de la lista con su tamaño actual.

Solo llama:

arr.add(10)

agregar el número entero a su ArrayList

Hunter McMillen
fuente
1

Aunque su lista de arrays tiene una capacidad de 10, la lista real no tiene elementos aquí. El método add se usa para insertar un elemento en la lista real. Como no tiene elementos, no puede insertar un elemento en el índice de 5.

roll1987
fuente
1

Si desea agregar 10 elementos a su ArrayListpuede intentar eso:

for (int i = 0; i < 10; i++)
    arr.add(i);

Si ya ha declarado una variable de tamaño de matriz, usaría la variable en sizelugar del número '10'

pantera
fuente
1

Me enfrenté a un problema similar, y solo sabiendo que arrayList es una implementación de matriz redimensionable de la interfaz List, también espero que pueda agregar elementos a cualquier punto, pero al menos tenga la opción de definir el tamaño inicial. De todos modos, primero puede crear una matriz y convertirla en una lista como:

  int index = 5;
  int size = 10;

  Integer[] array = new Integer[size];
  array[index] = value;
  ...
  List<Integer> list = Arrays.asList(array);

o

  List<Integer> list = Arrays.asList(new Integer[size]);
  list.set(index, value);
deshacer
fuente
0

ArrayList myList = new ArrayList (10);

//  myList.add(3, "DDD");
//  myList.add(9, "III");
    myList.add(0, "AAA");
    myList.add(1, "BBB");

    for(String item:myList){
        System.out.println("inside list : "+item);
    }

/ * Declarar que la capa inicial de arraylist no es más que ahorrar tiempo de cambio internamente; cuando agregamos el elemento internamente, verificamos la capa para aumentar la capa, podría agregar el elemento en el índice 0 inicialmente, luego en 1 y así sucesivamente. * /

sambhu
fuente
0

Mis dos centavos en adelante Stream. Creo que es mejor usar

IntStream.generate(i -> MyClass.contruct())
         .limit(INT_SIZE)
         .collect(Collectors.toList());

con la flexibilidad de poner cualquier valor inicial.

anch2150
fuente