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()); // 0LinkedList 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))); // falseIterator와 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()); // HelloListIterator를 사용할 시점
다음과 같은 경우 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 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- Iterable과 Iterator 계약
- 사용자 정의 반복자 구현
- ListIterator와 양방향 순회
- 빠른 실패 반복자와 안전한 반복자