Skip to content

25. L’API List

Indice


Nel Collections Framework, una List rappresenta una collezione ordinata, basata su indice, che consente duplicati.

L’interfaccia List estende Collection ed è implementata da:

List
├── ArrayList (Array ridimensionabile — accesso casuale veloce, inserimenti/rimozioni più lenti nel mezzo)
├── LinkedList (Lista doppiamente collegata — inserimenti/rimozioni veloci, accesso casuale più lento)
└── Vector (Lista sincronizzata legacy — raramente usata oggi)

Note

Vector è legacy e sincronizzato — evitarlo a meno che non sia esplicitamente richiesto.

25.1 Caratteristiche delle List

  • Ordinate — gli elementi preservano l’ordine di inserimento.
  • Indicizzate — accessibili tramite get(int) e set(int,E).
  • Consentono duplicati — List non impone unicità.
  • Possono contenere null — a meno di usare implementazioni speciali.

25.2 Creare List (Costruttori)

25.2.1 Costruttori di ArrayList

List<String> a1 = new ArrayList<>();
List<String> a2 = new ArrayList<>(50); // capacità iniziale
List<String> a3 = new ArrayList<>(List.of("A", "B"));

Note

La capacità iniziale non è una dimensione. Decide solo quanti elementi l’array interno può contenere prima di ridimensionarsi.

25.2.2 Costruttori di LinkedList

List<String> l1 = new LinkedList<>();
List<String> l2 = new LinkedList<>(List.of("A", "B"));

Note

LinkedList implementa anche Deque.


25.3 Metodi Factory

25.3.1 List.of() (immutabile)

List<String> list1 = List.of("A", "B", "C");
list1.add("X"); // ❌ UnsupportedOperationException
list1.set(0, "Z"); // ❌ UnsupportedOperationException

Note

Tutte le liste List.of(): - non accettano i null - sono immutabili - lanciano UOE su modifiche strutturali

25.3.2 List.copyOf() (copia immutabile)

List<String> src = new ArrayList<>();
src.add("Hello");

List<String> copy = List.copyOf(src); // snapshot immutabile

25.3.3 Arrays.asList() (lista a dimensione fissa)

String[] arr = {"A", "B"};
List<String> list = Arrays.asList(arr);

list.set(0, "Z"); // OK
list.add("X"); // ❌ UOE — la dimensione è fissa

Note

La lista è supportata dall’array: modificare uno modifica anche l’altro.


25.4 Operazioni Fondamentali di List

25.4.1 Aggiungere Elementi

list.add("A");
list.add(1, "B"); // inserisce all’indice
list.addAll(otherList);
list.addAll(2, otherList);

25.4.2 Accedere agli Elementi

String x = list.get(0);
list.set(1, "NewValue");

Note

get() lancia IndexOutOfBoundsException per indici non validi.

Se si tenta di aggiornare un elemento in una List vuota, anche all’indice 0, si ottiene una IndexOutOfBoundsException

List<Integer> list = new ArrayList<Integer>();
list.add(3);
list.add(5);
System.out.println(list.toString());
list.clear();
list.set(0, 2);

Output

[3, 5]
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0

Warning

Chiamare get/set con un indice non valido lancia IndexOutOfBoundsException

25.4.3 Rimuovere Elementi

list.remove(0); // remove(int index) — rimuove per indice; remove(Object) — rimuove il primo elemento uguale
list.remove("A"); // rimuove la prima occorrenza
list.removeIf(s -> s.startsWith("X"));
list.clear();

25.4.4 Comportamenti e Caratteristiche Importanti

Operazione Comportamento Eccezione(i)
add(E) aggiunge sempre in coda
add(int,E) sposta gli elementi a destra IndexOutOfBoundsException
get(int) tempo costante per ArrayList, lineare per LinkedList IndexOutOfBoundsException
set(int,E) sostituisce l’elemento IndexOutOfBoundsException
remove(int) sposta gli elementi a sinistra IndexOutOfBoundsException
remove(Object) rimuove il primo elemento uguale

25.5 contains(), equals() e hashCode()

25.5.1 contains()

Il metodo contains() usa .equals() sugli elementi.

25.5.2 Uguaglianza delle List

List.equals() esegue un confronto elemento per elemento, in ordine.

List<String> a = List.of("A", "B");
List<String> b = List.of("A", "B");

System.out.println(a.equals(b)); // true

Note

  • L’ordine conta.
  • Il tipo di lista NON conta.

25.5.3 hashCode()

Calcolato in base al contenuto.


25.6 Iterare una List

25.6.1 Ciclo For Classico

for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}

25.6.2 Ciclo For Migliorato

for (String s : list) {
    System.out.println(s);
}

25.6.3 Iterator & ListIterator

Iterator<String> it = list.iterator();
while (it.hasNext()) { System.out.println(it.next()); }

ListIterator<String> lit = list.listIterator();
while (lit.hasNext()) {
    if (lit.next().equals("A")) lit.set("Z");
}

Warning

Tutti gli iteratori standard di List sono fail-fast: una modifica strutturale fuori dall’iteratore causa ConcurrentModificationException.

Note

Solo ListIterator supporta l’iterazione bidirezionale e la modifica.


25.7 Il Metodo subList()

subList() crea una vista di una porzione della lista, non una copia. Modificare una delle due può modificare l’altra.

25.7.1 Sintassi

List<E> subList(int fromIndex, int toIndex);

25.7.2 Regole

Regola Spiegazione
fromIndex inclusivo l’elemento a fromIndex è incluso
toIndex esclusivo l’elemento a toIndex NON è incluso
La vista è supportata dalla lista originale modificare una modifica l’altra
Modifica strutturale del padre invalida la subList → ConcurrentModificationException

25.7.3 Esempi

List<String> list = new ArrayList<>(List.of("A", "B", "C", "D"));
List<String> view = list.subList(1, 3);
// view = ["B", "C"]

view.set(0, "X");
// list = ["A", "X", "C", "D"]
// view = ["X", "C"]

25.7.4 Modificare la lista padre invalida la vista

List<String> list = new ArrayList<>(List.of("A","B","C","D"));
List<String> view = list.subList(1, 3);

list.add("E"); // modifica strutturale della lista padre

view.get(0); // ❌ ConcurrentModificationException

25.7.5 Modificare la subList modifica il padre

view.remove(1);
// rimuove "C" sia dalla view che dalla lista padre

25.7.6 Svuotare la subList svuota parte della lista padre

view.clear();
// rimuove gli indici 1 e 2 dalla lista padre

25.7.7 Trappole Comuni

  • Supporre che subList sia indipendente: è una vista, non una copia
  • Supporre che subList consenta il ridimensionamento: funziona solo su liste padre modificabili
  • Dimenticare che le modifiche al padre invalidano la vista causando ConcurrentModificationException
  • Aspettative errate sugli indici: l’indice finale è esclusivo

25.8 Tabella Riassuntiva delle Operazioni Importanti

Operazione ArrayList LinkedList List Immutabili
add(E) veloce veloce ❌ non supportato
add(index,E) lento (shift) veloce
get(index) veloce lento veloce
remove(index) lento lento (a meno che si rimuova primo/ultimo)
remove(Object) più lento più lento
set(index,E) veloce lento
iterator() veloce veloce veloce
listIterator() veloce veloce veloce
contains(Object) O(n) O(n) O(n)
```