← Назад к вопросам

Как можно обратиться на предыдущий элемент в LinkedList?

1.3 Junior🔥 211 комментариев
#Коллекции#ООП#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как обратиться на предыдущий элемент в LinkedList

LinkedList в Java — это двусвязный список (doubly-linked list), где каждый элемент имеет ссылку на следующий и предыдущий элемент. Существует несколько способов получить доступ к предыдущему элементу.

1. Использование ListIterator

Наиболее универсальный способ — это использование ListIterator, который поддерживает движение в обе стороны:

LinkedList<String> list = new LinkedList<>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");

ListIterator<String> iterator = list.listIterator(2); // Начинаем с индекса 2

while (iterator.hasNext()) {
    System.out.println("Forward: " + iterator.next());
}

while (iterator.hasPrevious()) {
    System.out.println("Backward: " + iterator.previous());
}

Вывод:

Forward: C
Forward: D
Backward: D
Backward: C
Backward: B
Backward: A

2. Методы ListIterator

ListIterator<Integer> it = list.listIterator(2);

// Проверка наличия следующего элемента
if (it.hasNext()) {
    int next = it.next();  // Получить следующий и переместить курсор
}

// Проверка наличия предыдущего элемента
if (it.hasPrevious()) {
    int prev = it.previous();  // Получить предыдущий и переместить курсор
}

// Получить индекс
int nextIndex = it.nextIndex();      // индекс следующего
int previousIndex = it.previousIndex(); // индекс предыдущего

3. Пример с условием на предыдущий элемент

LinkedList<String> list = new LinkedList<>(Arrays.asList("A", "B", "C", "D", "E"));
ListIterator<String> iterator = list.listIterator(3);

while (iterator.hasPrevious()) {
    String previous = iterator.previous();
    System.out.println(previous);
    
    // Если нашли нужный элемент, вставим что-нибудь
    if (previous.equals("B")) {
        iterator.add("B1");
    }
}

4. Навигация по списку в обе стороны

public static void bidirectionalTraversal(LinkedList<String> list) {
    ListIterator<String> it = list.listIterator(list.size() / 2);
    
    // Сначала вперёд
    System.out.println("Forward from middle:");
    while (it.hasNext()) {
        System.out.println(it.next());
    }
    
    // Потом назад
    System.out.println("Backward to start:");
    while (it.hasPrevious()) {
        System.out.println(it.previous());
    }
}

5. Почему нельзя с обычным Iterator?

// ❌ Это не работает - Iterator не поддерживает hasPrevious()
Iterator<String> it = list.iterator();
// it.hasPrevious();  // Ошибка компиляции!
// it.previous();     // Ошибка компиляции!

// ✅ Нужно использовать ListIterator
ListIterator<String> listIt = list.listIterator();
listIt.hasPrevious();  // Правильно
listIt.previous();     // Правильно

6. Удаление и изменение через ListIterator

LinkedList<String> list = new LinkedList<>(Arrays.asList("A", "B", "C", "D"));
ListIterator<String> it = list.listIterator(2); // Начинаем с C

it.next();  // Переместимся на D
it.remove(); // Удалим D

it.previous(); // Вернёмся на C
it.set("C_modified"); // Заменим C

it.add("X"); // Вставим X после текущей позиции

System.out.println(list); // [A, B, C_modified, X]

7. Поиск и получение соседних элементов

public class ListHelper {
    public static <T> T getPrevious(LinkedList<T> list, T element) {
        ListIterator<T> it = list.listIterator();
        
        while (it.hasNext()) {
            if (it.next().equals(element)) {
                if (it.hasPrevious()) {
                    it.previous();  // Вернёмся на текущий
                    it.previous();  // Перейдём на предыдущий
                    return it.next(); // Получим предыдущий и переместимся на него
                }
            }
        }
        return null;
    }
    
    public static <T> T getNext(LinkedList<T> list, T element) {
        ListIterator<T> it = list.listIterator();
        
        while (it.hasNext()) {
            if (it.next().equals(element)) {
                if (it.hasNext()) {
                    return it.next();
                }
            }
        }
        return null;
    }
}

// Использование
LinkedList<String> list = new LinkedList<>(Arrays.asList("A", "B", "C", "D"));
String prev = ListHelper.getPrevious(list, "C"); // Вернёт "B"
String next = ListHelper.getNext(list, "C");     // Вернёт "D"

8. Сравнение подходов

LinkedList<Integer> list = new LinkedList<>(Arrays.asList(1, 2, 3, 4, 5));

// ❌ Неэффективно - итерирует по каждому элементу
int index = 2;
Integer prev1 = list.get(index - 1);  // O(n) для LinkedList!

// ✅ Эффективно - использует итератор
ListIterator<Integer> it = list.listIterator(index);
it.next();  // Переместимся на нужный элемент
it.previous();  // Вернёмся на предыдущий
it.previous();  // Получим предыдущий
Integer prev2 = it.next();  // Получим значение

9. Практический пример: проверка отсортированного списка

public static <T extends Comparable<T>> boolean isSorted(LinkedList<T> list) {
    ListIterator<T> it = list.listIterator(1);
    
    while (it.hasNext()) {
        T current = it.next();
        T previous = list.get(it.previousIndex() - 1);
        
        if (previous.compareTo(current) > 0) {
            return false;  // Нарушение порядка
        }
    }
    return true;
}

10. Полный пример: двусвязный обход

public class LinkedListNavigator {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>(Arrays.asList("A", "B", "C", "D", "E"));
        
        ListIterator<String> it = list.listIterator(2);
        System.out.println("Starting at index 2 (C)");
        
        // Несколько раз вперёд
        for (int i = 0; i < 2 && it.hasNext(); i++) {
            System.out.println("Next: " + it.next());
        }
        
        // Несколько раз назад
        for (int i = 0; i < 3 && it.hasPrevious(); i++) {
            System.out.println("Previous: " + it.previous());
        }
        
        // Текущая позиция
        System.out.println("Current next index: " + it.nextIndex());
        System.out.println("Current previous index: " + it.previousIndex());
    }
}

Ключевые выводы

  1. Используй ListIterator — это основной способ доступа к предыдущему элементу
  2. Отличие от Iterator — ListIterator добавляет методы hasPrevious(), previous(), set(), add()
  3. Производительность — в LinkedList использование итератора эффективнее, чем get(index)
  4. Двусвязный список — LinkedList позволяет эффективно двигаться в обе стороны
  5. Модификация — можно удалять и добавлять элементы через итератор

Этот подход даёт максимальную гибкость при работе со списками в Java.