ArrayList în Java

Lista implementată cu un array intern care crește automat; acces foarte rapid după index. Cea mai folosită listă din Java.

Sintaxă
new ArrayList<>()
new ArrayList<>(int capacitateInitiala)
new ArrayList<>(Collection<? extends E> c)

void ensureCapacity(int minCapacity)
void trimToSize()

Ce face ArrayList

ArrayList ține elementele într-un array intern. Când array-ul se umple, clasa creează unul mai mare (cam de 1,5 ori) și copiază elementele în el. Din această cauză, get(i) și set(i, x) sunt foarte rapide, iar adăugarea la final este rapidă în medie. Inserarea sau ștergerea la început ori la mijloc mută toate elementele de după.

Capacitatea (mărimea array-ului intern) nu este același lucru cu size() (câte elemente ai pus). ensureCapacity(n) mărește dinainte array-ul, ca să încapă cel puțin n elemente fără alte realocări; e util când știi că urmează să adaugi foarte multe elemente. trimToSize() face capacitatea egală cu size() și eliberează memoria nefolosită.

Capacitatea nu se vede din exterior: nu există o metodă publică capacity(). Pentru programe obișnuite nu ai nevoie de aceste două metode; contează doar la liste foarte mari.

Parametri

Parametru Descriere
capacitateInitiala Câte elemente încap înainte de prima realocare. Lista pornește tot goală (size() == 0).
c O colecție ale cărei elemente sunt copiate în lista nouă, în aceeași ordine.
minCapacity Pentru ensureCapacity: capacitatea minimă dorită.

Ce returnează

Constructorul creează lista. ensureCapacity și trimToSize nu returnează nimic (void).

Exemple

Exemplul 1: Crearea și modificarea unui ArrayList

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> cumparaturi = new ArrayList<>();
        cumparaturi.add("pâine");
        cumparaturi.add("lapte");
        cumparaturi.add(0, "cafea");       // inserare la început
        cumparaturi.set(2, "lapte bătut");  // înlocuire

        System.out.println(cumparaturi);

        List<String> copie = new ArrayList<>(cumparaturi);   // copie independentă
        copie.remove("cafea");
        System.out.println("Original: " + cumparaturi);
        System.out.println("Copie:    " + copie);
    }
}

Rezultat

[cafea, pâine, lapte bătut]
Original: [cafea, pâine, lapte bătut]
Copie:    [pâine, lapte bătut]

Exemplul 2: ensureCapacity înainte de multe adăugări

Rezervăm loc pentru un milion de elemente, apoi le adăugăm fără realocări intermediare. Rezultatul este același; diferă doar viteza.

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> numere = new ArrayList<>();
        numere.ensureCapacity(1_000_000);
        for (int i = 1; i <= 1_000_000; i++) {
            numere.add(i);
        }
        System.out.println("Elemente: " + numere.size());
        System.out.println("Ultimul: " + numere.get(numere.size() - 1));
    }
}

Rezultat

Elemente: 1000000
Ultimul: 1000000

Exemplul 3: trimToSize după ce lista nu mai crește

Lista a fost creată cu capacitatea 1000, dar are doar 3 elemente. trimToSize() micșorează array-ul intern la 3; conținutul rămâne neschimbat.

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> elevi = new ArrayList<>(1000);
        elevi.add("Ana");
        elevi.add("Mihai");
        elevi.add("Ioana");
        elevi.trimToSize();
        System.out.println(elevi + ", size = " + elevi.size());
        elevi.add("Radu");        // lista poate crește în continuare
        System.out.println(elevi);
    }
}

Rezultat

[Ana, Mihai, Ioana], size = 3
[Ana, Mihai, Ioana, Radu]

Greșeli frecvente

  • Crezi că new ArrayList<>(10) creează 10 elemente. Creează o listă goală cu loc pentru 10; get(0) aruncă IndexOutOfBoundsException.
  • Ștergi des elemente de la începutul unui ArrayList mare (de exemplu ca o coadă). Fiecare ștergere mută toate elementele; pentru cozi folosește ArrayDeque.
  • Apelezi trimToSize() în buclă, după fiecare adăugare. Fiecare apel copiază array-ul și anulează avantajul creșterii automate.

Comenzi înrudite

  • List: Interfața pentru liste ordonate: elementele au poziții (0, 1, 2…), se pot repeta și se pot citi după index.
  • LinkedList: Listă dublu înlănțuită: adăugare și ștergere rapide la ambele capete; implementează și List, și Deque.
  • List.add: Adaugă un element (sau toate elementele altei colecții) la sfârșitul listei ori la o poziție dată.
  • List.get: get citește elementul de la o poziție; set îl înlocuiește și returnează valoarea veche.
  • ArrayDeque: Implementarea recomandată pentru cozi și stive: un array circular care crește automat, rapid la ambele capete.
  • Arrays.asList: Returnează o listă de mărime fixă legată de un array: poți citi și schimba elemente cu set, dar nu poți adăuga sau șterge.