0Pricing
Java Academy · 강의

ListIterator와 양방향 순회

ListIterator로 리스트를 앞뒤로 순회하고 순회 중 요소를 수정합니다.

ListIterator와 양방향 순회은(는) CoddyKit의 무료 Java Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Java Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

ListIterator

ListIterator<T>는 Iterator<T>를 확장하여 역방향 순회, 인덱스 기반 위치 지정, 순회 중 요소 추가 및 교체 기능을 제공합니다.

ListIterator API

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

특정 위치에서 시작하기

listIterator(index)를 사용하면 특정 인덱스에서 시작하는 ListIterator를 만들 수 있습니다.

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() 사용

set()은 next() 또는 previous()가 마지막으로 반환한 요소를 바꿉니다. LinkedList에서는 O(1), ArrayList에서도 O(1)이므로 효율적입니다.

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() 사용

add(element)는 다음 위치 앞에 요소를 삽입합니다. 추가된 요소는 이후 next() 호출에서 반환되지 않습니다. 커서의 이미 "뒤쪽"에 있기 때문입니다.

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]

리스트를 제자리에서 뒤집기

새 리스트를 할당하지 않고 ListIterator를 사용해 O(n)에 리스트를 뒤집습니다.

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

nextIndex()는 next()가 반환할 요소의 인덱스를 반환합니다. previousIndex()는 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

LinkedList ListIterator 성능

LinkedList의 ListIterator는 포인터를 따라 이동하므로 next/previous를 O(1)에 수행합니다. LinkedList에서 get(i)는 O(n)이므로 효율적으로 순회하려면 ListIterator를 사용하십시오.

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]

ListIterator로 회문 확인

양방향 순회의 우아한 예로, 리스트가 회문인지 확인합니다.

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

Iterator와 ListIterator 비교

주요 차이점:

  • Iterator: 정방향만 지원하며 hasNext/next/remove를 제공합니다.
  • ListIterator: 양방향을 지원하며 hasPrevious/previous, nextIndex/previousIndex, set/add를 제공합니다.
  • ListIterator는 List에서만 사용할 수 있습니다(Set과 Queue에서는 사용할 수 없습니다).

ListIterator로 실행 취소 및 다시 실행

효율적인 문자 이동을 위해 ListIterator를 사용하는 커서 기반 텍스트 편집기입니다.

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

ListIterator를 사용할 시점

다음과 같은 경우 ListIterator를 사용하십시오.

  • 리스트를 역방향으로 순회해야 할 때
  • 순회 중 set()으로 요소를 바꿔야 할 때
  • 순회 중 add()로 요소를 삽입해야 할 때
  • nextIndex()/previousIndex()로 위치를 추적해야 할 때

빠른 확인

ListIterator.set()은 무엇을 수행합니까?

복습: ListIterator와 양방향 순회

핵심 내용:

  • ListIterator는 hasPrevious(), previous(), set(), add()를 추가하여 Iterator를 확장합니다.
  • 특정 위치에서 ListIterator를 만드려면 listIterator(index)를 사용합니다.
  • set()은 next() 또는 previous()가 마지막으로 반환한 요소를 바꿉니다.
  • add()는 현재 커서 위치 앞에 요소를 삽입합니다.
  • nextIndex()와 previousIndex()는 현재 위치를 확인할 수 있게 합니다.
  • O(1) 순회와 수정을 위해 LinkedList ListIterator를 사용하십시오.

자주 묻는 질문

“ListIterator와 양방향 순회” 강의는 무료인가요?

네 — “ListIterator와 양방향 순회” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Java Academy 강의 전체를 잠금 해제할 수 있습니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“ListIterator와 양방향 순회”에서 뭘 배우나요?

ListIterator로 리스트를 앞뒤로 순회하고 순회 중 요소를 수정합니다. 브라우저에서 직접 실행하는 실습 코드로 Java Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Java Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Java Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“ListIterator와 양방향 순회” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Java Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Java Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. Iterable과 Iterator 계약
  2. 사용자 정의 반복자 구현
  3. ListIterator와 양방향 순회
  4. 빠른 실패 반복자와 안전한 반복자
← Java Academy(으)로 돌아가기