Dimensione iniziale per ArrayList


257

È possibile impostare la dimensione iniziale per un ArrayList facendo

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

Tuttavia, non puoi farlo

arr.add(5, 10);

perché provoca un'eccezione fuori limite.

A che serve impostare una dimensione iniziale se non riesci ad accedere allo spazio che hai assegnato?

La funzione di aggiunta è definita come add(int index, Object element)quindi non sto aggiungendo all'indice 10.


52
In realtà, non è ovvio dai documenti che un elenco deve avere almeno n elementi aggiunti prima di poter inserire l' set/addelemento n-1 .
Percezione

5
Percezione: non so se sia ovvio, ma è specificato. Bisogna leggere attentamente JavaDoc. Lancia: IndexOutOfBoundsException - se indice fuori range (indice <0 || indice> = dimensione ()).
Natix,

3
Hm, il costruttore dice "Costruisce un elenco vuoto con la capacità iniziale specificata", prendendo la nozione di un elenco vuoto, non può esserci un indice 5. Ma sono d'accordo che questo potrebbe non essere visibile a prima vista ...
quaylar

12
Penso sia anche corretto affermare che se si inizializza un array su un valore specifico, si supporranno che siano disponibili indici inferiori a quel valore — e questo è un ArrayList. Personalmente, vorrei un metodo che mi permettesse di impostare una dimensione tale da poter inserire le cose in indici specifici. Questo metodo sembra notevolmente assente.
Andrew Wyld,

1
Quale numbskull ha progettato le collezioni in questo modo ?! Ciò forza il lavoro ridondante per l'istanza parallela di una struttura con elementi a lunghezza variabile (ad es. ArrayList <String []> in cui ogni array può avere una lunghezza diversa). Se la memoria è già allocata, quindi l'elenco non necessita di riallocazione dopo l'aggiunta di N elementi, tali indici dovrebbero essere direttamente accessibili dall'inizio. Nessuno in Oracle ha imparato questo schema dopo C / C ++, C #, Objective C e Swift ?!
patrickjp93,

Risposte:


387

Stai confondendo la dimensione dell'elenco di array con la sua capacità:

  • la dimensione è il numero di elementi nell'elenco;
  • la capacità è quanti elementi l'elenco può potenzialmente ospitare senza riallocare le sue strutture interne.

Quando chiami new ArrayList<Integer>(10), stai impostando la capacità iniziale dell'elenco , non le sue dimensioni. In altre parole, se costruito in questo modo, l'elenco di array inizia a essere vuoto.

Un modo per aggiungere dieci elementi all'elenco di array è utilizzare un ciclo:

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

Fatto ciò, ora puoi modificare gli elementi agli indici 0..9.


51
+1: un ciclo più corto è while(arr.size() < 10) arr.add(0);Può essere utile dire che la dimensione deve essere almeno 10. ad es. così puoi usarearr.set(9, n);
Peter Lawrey il

10
+1: Ottima risposta, darei +10 se potessi. Dall'API non è immediatamente ovvio il motivo per cui non è possibile impostare ENTRAMBE la dimensione iniziale e la capacità iniziale in una singola chiamata del costruttore. In un certo senso devi leggere l'API e dire "Oh, immagino che ArrayList non abbia un metodo o un costruttore per farlo"
demongolem,

@PeterLawrey Il tuo codice potrebbe essere più breve, ma contiene due chiamate di metodo per iterazione di loop, anziché solo una.
Neuralmer,

@neuralmer Mi aspetterei che size () e add () siano allineati, quindi non si verifica alcuna chiamata effettiva al metodo in fase di esecuzione.
Peter Lawrey,

109

Se vuoi un elenco con una dimensione predefinita puoi anche usare:

List<Integer> arr = Arrays.asList(new Integer[10]);

11
Un leggero svantaggio qui, il risultato Listè pieno di null. Con Guava possiamo fare Ints.asList(new int[10])che inizializzerà la nostra lista con 0s. Schema pulito però, grazie per l'esempio.
dimo414,

1
Le domande parlano di ArrayList <E>. Stai usando Elenco <E>. Nessuno ha osservato questo ??? Inoltre, hanno votato questa risposta irrilevante ! Non declassare la tua risposta perché non lo faccio mai. Semplicemente ... Godssake!
Apostolos,

3
@Apostolos ArrayListè un'implementazione Listdell'interfaccia e Arrays.asListrestituisce un ArrayList. Ti consiglio di cercare il polimorfismo.
Liam Potter,

Ciò restituisce tuttavia un elenco con una dimensione fissa. Prova di aggiungere altri elementi lanciUnsupportedOperationException
Koray Tugay

47

se si desidera utilizzare Collections.fill (list, obj); per riempire la lista con un oggetto ripetuto in alternativa puoi usare

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

la riga copia 10 volte 0 nella tua ArrayList


20

La capacità di un ArrayListnon è la stessa della sua dimensione . La dimensione è uguale al numero di elementi contenuti nella ArrayList(e qualsiasi altra Listimplementazione).

La capacità è solo la lunghezza dell'array sottostante utilizzato per archiviare internamente gli elementi di ArrayList, ed è sempre maggiore o uguale alla dimensione dell'elenco.

Quando si richiama set(index, element)l'elenco, si indexriferisce al numero effettivo degli elementi dell'elenco (= dimensione) (che è zero nel codice, quindi AIOOBEviene generato), non alla lunghezza dell'array (= capacità) (che è un dettaglio di implementazione specifico al ArrayList).

Il setmetodo è comune a tutte le Listimplementazioni, come ad esempio LinkedList, che non è effettivamente implementato da un array, ma come una catena di voci collegate.

Modifica : in realtà usi il add(index, element)metodo, no set(index, element), ma il principio è lo stesso qui.


10

Se si desidera aggiungere gli elementi con indice, è possibile invece utilizzare un array.

    String [] test = new String[length];
    test[0] = "add";

5
Inizialmente l'OP voleva usare un elenco ... non un array.
Stephan,

9

10 è la capacità iniziale dell'AL, non la dimensione (che è 0). Dovresti menzionare la capacità iniziale su un valore elevato quando avrai molti elementi, perché evita il sovraccarico di espandere la capacità mentre continui ad aggiungere elementi.


6

Immagino che una risposta esatta alla tua domanda sarebbe:

L'impostazione di una dimensione iniziale su un ArrayList riduce il numero. delle volte in cui deve avvenire la riassegnazione della memoria interna. L'elenco è supportato da un array. Se si specifica cioè la capacità iniziale 0, già al primo inserimento di un elemento l'array interno dovrebbe essere ridimensionato. Se hai un'idea approssimativa di quanti elementi il ​​tuo elenco potrebbe contenere, l'impostazione della capacità iniziale ridurrebbe il nr. delle allocazioni di memoria che si verificano mentre si utilizza l'elenco.


3

Questo potrebbe aiutare qualcuno -

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

3

Essendo in ritardo a questo, ma dopo Java 8 , trovo personalmente questo approccio seguente con l' StreamAPI più conciso e può essere un'alternativa alla risposta accettata .

Per esempio,

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

dove sizeè la Listdimensione desiderata e senza lo svantaggio menzionato qui , tutti gli elementi in Listsono inizializzati come 0.

(Ho fatto una ricerca veloce e non ho visto streamnessuna delle risposte pubblicate - non esitate a farmi sapere se questa risposta è ridondante e posso rimuoverla)


1

Al momento non ci sono elementi nella tua lista, quindi non puoi aggiungere all'indice 5 della lista quando non esiste. Stai confondendo la capacità dell'elenco con la sua dimensione attuale.

Chiama soltanto:

arr.add(10)

per aggiungere il numero intero alla tua ArrayList


1

Sebbene il tuo arraylist abbia una capacità di 10, la lista reale non ha elementi qui. Il metodo add viene utilizzato per inserire un elemento nell'elenco reale. Poiché non ha elementi, non è possibile inserire un elemento nell'indice di 5.


1

Se vuoi aggiungere 10 elementi al tuo ArrayListpuoi provare che:

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

Se hai già dichiarato una variabile di dimensione dell'array, useresti la variabile sizeanziché il numero '10'


1

Ho affrontato il problema simile e sapendo che arrayList è un'implementazione di array ridimensionabile dell'interfaccia Elenco, mi aspetto anche che tu possa aggiungere elementi a qualsiasi punto, ma almeno hai la possibilità di definire la dimensione iniziale. Ad ogni modo, puoi prima creare un array e convertirlo in un elenco come:

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

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

/ * Dichiarare che la capasità iniziale dell'arraylist non è altro che risparmiare tempo di spostamento all'interno; quando aggiungiamo l'elemento internamente, esso controlla la capasità per aumentare la capasità, è possibile aggiungere l'elemento all'indice 0 inizialmente, quindi 1 e così via. * /


0

I miei due centesimi in poi Stream. Penso che sia meglio usare

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

con la flessibilità di mettere qualsiasi valore iniziale.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.