0Pricing
Java Academy · Lección

ListIterator y recorrido bidireccional

Use ListIterator para recorrer listas hacia delante y hacia atrás, y modificar elementos durante la iteración.

ListIterator y recorrido bidireccional es una lección gratuita de Java Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Java Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Java Academy incluye 4 lecciones en total.

ListIterator

ListIterator<T> extiende Iterator<T> con recorrido hacia atrás, posicionamiento mediante índices y la posibilidad de añadir y reemplazar elementos durante el recorrido.

API de ListIterator

Métodos adicionales a los de Iterator: hasPrevious(), previous(), nextIndex(), previousIndex(), set() y 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

Comenzar en una posición

Cree un ListIterator comenzando en un índice específico 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 la iteración

set() reemplaza el último elemento devuelto por next() o previous(). Es una operación eficiente: O(1) para LinkedList y O(1) para 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 la iteración

add(element) inserta el elemento antes de la siguiente posición. Una llamada posterior a next() no devuelve el elemento añadido, ya que este queda detrás del cursor.

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]

Invertir una lista en el sitio

Uso de ListIterator para invertir una lista en O(n) sin asignar una lista nueva.

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 y previousIndex

nextIndex() devuelve el índice del elemento que devolvería next(). previousIndex() devuelve el índice del elemento que devolvería 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

Rendimiento de ListIterator en LinkedList

El ListIterator de LinkedList consigue O(1) para next/previous porque el recorrido sigue referencias. get(i) en LinkedList es O(n); use ListIterator para recorrerla de forma eficiente.

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]

Comprobar un palíndromo con ListIterator

Un ejemplo elegante de recorrido bidireccional: comprobar si una lista es un palíndromo.

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

Comparación entre Iterator y ListIterator

Diferencias principales:

  • Iterator: solo hacia delante, hasNext/next/remove
  • ListIterator: bidireccional, hasPrevious/previous, nextIndex/previousIndex, set/add
  • ListIterator solo se aplica a Lists, no a Set ni Queue

Deshacer y rehacer con ListIterator

Un editor de texto basado en un cursor que usa ListIterator para recorrer caracteres de forma eficiente al deshacer y rehacer acciones.

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

Cuándo usar ListIterator

Use ListIterator cuando necesite:

  • Recorrer una lista hacia atrás
  • Reemplazar elementos durante el recorrido con set()
  • Insertar elementos durante el recorrido con add()
  • Seguir la posición mediante nextIndex()/previousIndex()

Comprobación rápida

¿Qué hace ListIterator.set()?

Recapitulación: ListIterator y recorrido bidireccional

Aspectos clave:

  • ListIterator amplía Iterator con hasPrevious(), previous(), set() y add()
  • Cree un ListIterator en una posición específica: listIterator(index)
  • set() reemplaza el último elemento devuelto por next() o previous()
  • add() inserta el elemento antes de la posición actual del cursor
  • nextIndex() y previousIndex() permiten conocer la posición
  • Use el ListIterator de LinkedList para recorrer y modificar elementos en O(1)

Preguntas frecuentes

¿La lección «ListIterator y recorrido bidireccional» es gratis?

Sí — el texto completo de «ListIterator y recorrido bidireccional» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Java Academy, actualiza a CoddyKit PRO. El curso de Java Academy incluye 4 lecciones en total.

¿Qué aprenderé en «ListIterator y recorrido bidireccional»?

Use ListIterator para recorrer listas hacia delante y hacia atrás, y modificar elementos durante la iteración. Practicas Java Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Java Academy?

No se requiere experiencia previa. Java Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.

¿Cuánto tiempo toma la lección «ListIterator y recorrido bidireccional»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Java Academy?

Sí. Cada lección de Java Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Contratos de Iterable e Iterator
  2. Implementación de un iterador personalizado
  3. ListIterator y recorrido bidireccional
  4. Iteradores fail-fast frente a fail-safe
← Volver a Java Academy