0Pricing
Java Academy · บทเรียน

ListIterator และการวนดูแบบสองทิศทาง

ใช้ ListIterator วนดูรายการไปข้างหน้าและย้อนกลับ พร้อมแก้ไของค์ประกอบระหว่างการวนซ้ำ

ListIterator และการวนดูแบบสองทิศทาง เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

ListIterator

ListIterator<T> ขยายความสามารถจาก Iterator<T> ด้วยการท่องย้อนกลับ การระบุตำแหน่งตามดัชนี และความสามารถในการเพิ่มและแทนที่สมาชิกระหว่างการวนซ้ำ

API ของ ListIterator

เมธอดเพิ่มเติมนอกเหนือจากตัววนซ้ำ ได้แก่ 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 โดยเริ่มต้นที่ดัชนีที่ระบุด้วย 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() ระหว่างการวนซ้ำ

set() จะแทนที่องค์ประกอบล่าสุดที่ส่งคืนโดย next() หรือ previous() การดำเนินการนี้มีประสิทธิภาพ โดยใช้เวลา O(1) สำหรับ LinkedList และ O(1) สำหรับ 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() ระหว่างการวนซ้ำ

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

ListIterator ของ LinkedList ทำให้ next/previous ใช้เวลา O(1) เพราะการเคลื่อนที่เป็นการติดตามตัวชี้ ส่วน get(i) บน LinkedList ใช้เวลา 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

ความแตกต่างสำคัญ:

  • ตัววนซ้ำ: เดินหน้าได้ทิศทางเดียว มี hasNext/next/remove
  • ListIterator: เดินทางได้สองทิศทาง มี hasPrevious/previous, nextIndex/previousIndex และ set/add
  • ListIterator ใช้ได้เฉพาะกับรายการ ไม่ใช่ 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()
  • สร้าง ListIterator ที่ตำแหน่งเฉพาะได้ด้วย listIterator(index)
  • set() จะแทนที่องค์ประกอบล่าสุดที่ next() หรือ previous() ส่งคืน
  • add() จะแทรกองค์ประกอบก่อนตำแหน่งปัจจุบันของเคอร์เซอร์
  • nextIndex() และ previousIndex() ให้ข้อมูลเกี่ยวกับตำแหน่ง
  • ใช้ LinkedList ListIterator เพื่อการเคลื่อนที่และแก้ไขที่ใช้เวลา O(1)

คำถามที่พบบ่อย

บทเรียน “ListIterator และการวนดูแบบสองทิศทาง” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ListIterator และการวนดูแบบสองทิศทาง” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ListIterator และการวนดูแบบสองทิศทาง”

ใช้ ListIterator วนดูรายการไปข้างหน้าและย้อนกลับ พร้อมแก้ไของค์ประกอบระหว่างการวนซ้ำ คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “ListIterator และการวนดูแบบสองทิศทาง” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม

ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. สัญญาของ Iterable และ Iterator
  2. การสร้าง Iterator แบบกำหนดเอง
  3. ListIterator และการวนดูแบบสองทิศทาง
  4. Iterator แบบหยุดเร็วกับแบบปลอดภัย
← กลับไปที่ Java Academy