0Pricing
Java Academy · Lezione

ListIterator e attraversamento bidirezionale

Utilizzi ListIterator per attraversare le liste in avanti e all'indietro e modificare gli elementi durante l'iterazione.

ListIterator e attraversamento bidirezionale è una lezione Java Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Java Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Java Academy include 4 lezioni in totale.

ListIterator

ListIterator<T> estende Iterator<T> con l'attraversamento all'indietro, il posizionamento basato sugli indici e la possibilità di aggiungere e sostituire elementi durante l'iterazione.

API di ListIterator

Metodi aggiuntivi rispetto a Iterator: hasPrevious(), previous(), nextIndex(), previousIndex(), set(), add().

import java.util.*;

List<String> list = new ArrayList<>(List.of("A", "B", "C", "D"));
ListIterator<String> lit = list.listIterator();

// Forward traversal
while (lit.hasNext()) {
    System.out.print(lit.nextIndex() + ":" + lit.next() + " ");
}
// 0:A 1:B 2:C 3:D

System.out.println();

// Backward traversal
while (lit.hasPrevious()) {
    System.out.print(lit.previousIndex() + ":" + lit.previous() + " ");
}
// 3:D 2:C 1:B 0:A

Partire da una posizione

Crei un ListIterator a partire da un indice specifico con listIterator(index).

List<Integer> nums = new ArrayList<>(List.of(10, 20, 30, 40, 50));

// Start at index 2 (30)
ListIterator<Integer> lit = nums.listIterator(2);

System.out.println(lit.next());     // 30
System.out.println(lit.next());     // 40
System.out.println(lit.previous()); // 40
System.out.println(lit.previous()); // 30
System.out.println(lit.previous()); // 20

set() durante l'iterazione

set() sostituisce l'ultimo elemento restituito da next() o previous(). Questa operazione è efficiente: O(1) per LinkedList e O(1) per ArrayList.

List<String> words = new ArrayList<>(List.of("hello", "world", "java"));
ListIterator<String> lit = words.listIterator();

while (lit.hasNext()) {
    String word = lit.next();
    lit.set(word.toUpperCase()); // replace each with uppercase
}

System.out.println(words); // [HELLO, WORLD, JAVA]

add() durante l'iterazione

add(element) inserisce l'elemento prima della posizione successiva. L'elemento aggiunto non viene restituito da una successiva chiamata a next(): si trova già "dietro" il cursore.

List<Integer> numbers = new ArrayList<>(List.of(1, 2, 3));
ListIterator<Integer> lit = numbers.listIterator();

while (lit.hasNext()) {
    int n = lit.next();
    lit.add(n * 10); // insert n*10 after each element
}

System.out.println(numbers); // [1, 10, 2, 20, 3, 30]

Invertire una lista sul posto

Utilizzare ListIterator per invertire una lista in O(n) senza allocare una nuova lista.

static <T> void reverse(List<T> list) {
    ListIterator<T> front = list.listIterator(0);
    ListIterator<T> back  = list.listIterator(list.size());

    for (int i = 0, n = list.size() / 2; i < n; i++) {
        T frontVal = front.next();
        T backVal  = back.previous();
        front.set(backVal);
        back.set(frontVal);
    }
}

List<String> data = new ArrayList<>(List.of("a","b","c","d","e"));
reverse(data);
System.out.println(data); // [e, d, c, b, a]

nextIndex e previousIndex

nextIndex() restituisce l'indice dell'elemento che verrebbe restituito da next(). previousIndex() restituisce l'indice dell'elemento che verrebbe restituito da previous().

List<String> list = List.of("X", "Y", "Z");
ListIterator<String> lit = list.listIterator();

System.out.println(lit.nextIndex());     // 0
System.out.println(lit.previousIndex()); // -1 (before start)

lit.next(); // consume X
System.out.println(lit.nextIndex());     // 1
System.out.println(lit.previousIndex()); // 0

Prestazioni di ListIterator con LinkedList

Il ListIterator di LinkedList raggiunge O(1) per next/previous perché l'attraversamento segue i puntatori. get(i) su LinkedList è O(n): utilizzi ListIterator per attraversare la lista in modo efficiente.

import java.util.*;

LinkedList<Integer> list = new LinkedList<>();
for (int i = 0; i < 5; i++) list.add(i * 10);

// Efficient: O(n) total for traversal via ListIterator
ListIterator<Integer> lit = list.listIterator();
while (lit.hasNext()) {
    int val = lit.next();
    if (val == 20) lit.set(99); // O(1) update
}
System.out.println(list); // [0, 10, 99, 30, 40]

Verifica di un palindromo con ListIterator

Un elegante esempio di attraversamento bidirezionale: verificare se una lista è un palindromo.

static <T> boolean isPalindrome(List<T> list) {
    ListIterator<T> front = list.listIterator(0);
    ListIterator<T> back  = list.listIterator(list.size());

    for (int i = 0, n = list.size() / 2; i < n; i++) {
        if (!front.next().equals(back.previous())) return false;
    }
    return true;
}

System.out.println(isPalindrome(List.of(1, 2, 3, 2, 1))); // true
System.out.println(isPalindrome(List.of(1, 2, 3, 4)));    // false

Confronto tra Iterator e ListIterator

Differenze principali:

  • Iterator: solo in avanti, hasNext/next/remove
  • ListIterator: bidirezionale, hasPrevious/previous, nextIndex/previousIndex, set/add
  • ListIterator solo per le Lists (non per Set o Queue)

Undo/Redo con ListIterator

Un editor di testo basato su un cursore che utilizza ListIterator per una navigazione efficiente dei caratteri durante le operazioni di undo/redo.

import java.util.*;

class TextEditor {
    private final LinkedList<Character> chars = new LinkedList<>();
    private ListIterator<Character> cursor;

    TextEditor() { cursor = chars.listIterator(); }

    void type(char c) { cursor.add(c); } // insert before cursor

    void moveCursorLeft()  { if (cursor.hasPrevious()) cursor.previous(); }
    void moveCursorRight() { if (cursor.hasNext()) cursor.next(); }

    void backspace() {
        if (cursor.hasPrevious()) { cursor.previous(); cursor.remove(); }
    }

    String text() {
        StringBuilder sb = new StringBuilder();
        chars.forEach(sb::append);
        return sb.toString();
    }
}

TextEditor ed = new TextEditor();
ed.type('H'); ed.type('e'); ed.type('l'); ed.type('o');
ed.moveCursorLeft(); ed.moveCursorLeft();
ed.type('l');
System.out.println(ed.text()); // Hello

Quando utilizzare ListIterator

Utilizzi ListIterator quando ha bisogno di:

  • Attraversare una lista all'indietro
  • Sostituire elementi durante l'attraversamento con set()
  • Inserire elementi durante l'attraversamento con add()
  • Tenere traccia della posizione tramite nextIndex()/previousIndex()

Verifica rapida

Che cosa fa ListIterator.set()?

Riepilogo: ListIterator e attraversamento bidirezionale

Punti chiave:

  • ListIterator estende Iterator con hasPrevious(), previous(), set(), add()
  • Crei un ListIterator in una posizione specifica con listIterator(index)
  • set() sostituisce l'ultimo elemento restituito da next() o previous()
  • add() inserisce l'elemento prima della posizione corrente del cursore
  • nextIndex() e previousIndex() forniscono informazioni sulla posizione
  • Utilizzi ListIterator con LinkedList per un attraversamento e una modifica in O(1)

Domande Frequenti

La lezione «ListIterator e attraversamento bidirezionale» è gratuita?

Sì — il testo completo di «ListIterator e attraversamento bidirezionale» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Java Academy, passa a CoddyKit PRO. Il corso Java Academy include 4 lezioni in totale.

Cosa imparerò in «ListIterator e attraversamento bidirezionale»?

Utilizzi ListIterator per attraversare le liste in avanti e all'indietro e modificare gli elementi durante l'iterazione. Eserciti Java Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Java Academy?

Non è richiesta alcuna esperienza precedente. Java Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «ListIterator e attraversamento bidirezionale»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Java Academy?

Sì. Ogni lezione Java Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. I contratti di Iterable e Iterator
  2. Implementazione di un Iterator personalizzato
  3. ListIterator e attraversamento bidirezionale
  4. Iterator fail-fast e fail-safe
← Torna a Java Academy