“สวัสดี อามีโก้!”

“สวัสดี เอลลี่!”

"วันนี้ฉันอยากจะบอกคุณเกี่ยวกับ iterators"

"ตัววนซ้ำถูกประดิษฐ์ขึ้นจริงในเวลาเดียวกับคอลเลกชั่น จุดประสงค์หลักของคอลเลกชั่นคือการจัดเก็บองค์ประกอบ และจุดประสงค์หลักของตัววนซ้ำคือดึงองค์ประกอบเหล่านี้ทีละรายการ"

"อะไรเป็นเรื่องยากในการหาชุดองค์ประกอบ?"

"ประการแรก องค์ประกอบในบางคอลเลกชัน เช่น ชุด ไม่มีลำดับที่กำหนดไว้ และ/หรือลำดับเปลี่ยนแปลงตลอดเวลา"

"ประการที่สอง โครงสร้างข้อมูลบางอย่างอาจจัดเก็บวัตถุด้วยวิธีที่ซับซ้อนมาก: ในกลุ่มต่างๆ รายการ ฯลฯ กล่าวอีกนัยหนึ่ง การกระจายองค์ประกอบทั้งหมดตามลำดับจะเป็นงานที่ไม่สำคัญ"

"ประการที่สาม คอลเลกชันมีแนวโน้มที่จะเปลี่ยนแปลง สมมติว่าคุณตัดสินใจที่จะแสดงเนื้อหาทั้งหมดของคอลเลกชัน แต่ตรงกลางของเอาต์พุต JVM จะสลับไปยังเธรดอื่นที่มาแทนที่องค์ประกอบครึ่งหนึ่งของคอลเลกชัน ดังนั้นแทนที่จะเป็นเอาต์พุต คุณจะได้รับ ใครจะไปรู้ล่ะ"

"อืม..."

"แต่! สิ่งเหล่านี้เป็นปัญหาที่ตัววนซ้ำสามารถแก้ไขได้ตัววนซ้ำเป็นวัตถุพิเศษภายในคอลเลกชั่นที่ในแง่หนึ่ง สามารถเข้าถึงข้อมูลส่วนตัวทั้งหมดและรู้โครงสร้างภายในของมัน และในทางกลับกัน ใช้ส่วนต่อประสาน Iterator สาธารณะซึ่งช่วยให้ทุกคนรู้วิธีการทำงานกับมัน "

"ตัววนซ้ำบางตัวมีอาร์เรย์ภายในซึ่งองค์ประกอบทั้งหมดของคอลเลกชันจะถูกคัดลอกเมื่อสร้างตัววนซ้ำ สิ่งนี้ทำให้มั่นใจได้ว่าการเปลี่ยนแปลงใดๆ ที่ตามมากับคอลเลกชันจะไม่ส่งผลกระทบต่อจำนวนหรือลำดับขององค์ประกอบ"

"ฉันคิดว่าคุณเคยเจอสิ่งนี้เมื่อทำงานกับแต่ละอันคุณไม่สามารถวนซ้ำคอลเลกชั่นและลบองค์ประกอบออกจากมันได้ ทั้งหมดนี้เป็นเพราะวิธีการทำงานของตัววนซ้ำ"

"ในคอลเลกชันใหม่ที่เพิ่มในไลบรารีการทำงานพร้อมกัน ตัววนซ้ำจะถูกทำใหม่เพื่อขจัดปัญหานี้"

"ให้ฉันเตือนคุณว่าตัววนซ้ำทำงานอย่างไร"

"Java มีอินเทอร์เฟซ Iterator พิเศษ นี่คือวิธีการ:"

เมธอดของอินเทอร์เฟซ Iterator<E> คำอธิบาย
boolean hasNext() ตรวจสอบว่ามีองค์ประกอบเพิ่มเติมหรือไม่
E next() ส่งกลับองค์ประกอบปัจจุบันและย้ายไปยังองค์ประกอบถัดไป
void remove() ลบองค์ประกอบปัจจุบัน

"ตัววนซ้ำช่วยให้คุณได้รับองค์ประกอบทั้งหมดของคอลเล็กชันอย่างต่อเนื่อง มีเหตุผลมากกว่าที่จะคิดว่าตัววนซ้ำเป็นเหมือน InputStream นั่นคือมีข้อมูลทั้งหมด แต่หน้าที่คือส่งออกข้อมูลตามลำดับ"

"   เมธอด ถัดไป () ส่งคืนองค์ประกอบถัดไปในคอลเลกชัน"

" เมธอด hasNext () ใช้ในการตรวจสอบว่ามีองค์ประกอบเพิ่มเติมหรือไม่"

"และลบ () ลบองค์ประกอบปัจจุบัน"

"มีคำถามอะไรไหม?"

"ทำไมเมธอดถึงมีชื่อแปลกๆ ทำไมไม่เป็น isEmpty() และ getNextElement()"

“มันไม่เข้าท่ากว่าเหรอ?”

"มันสมเหตุสมผลกว่า แต่ชื่อมาจากภาษา C ++ ซึ่งตัววนซ้ำปรากฏขึ้นก่อนหน้านี้"

"เข้าใจแล้ว ไปต่อกันเถอะ"

"นอกจาก iterator แล้ว ยังมีอินเทอร์เฟซ Iterable ซึ่งต้องใช้งานโดยคอลเลกชั่นทั้งหมดที่รองรับ iterators มันมีเมธอดเดียว:"

เมธอดของอินเทอร์เฟซ Iterable<T> คำอธิบาย
Iterator<T>iterator() ส่งกลับวัตถุตัววนซ้ำ

"คุณสามารถใช้เมธอดนี้กับคอลเล็กชันใดก็ได้เพื่อให้ออบเจกต์ตัววนซ้ำเดินผ่านองค์ประกอบของมัน มาดูองค์ประกอบทั้งหมดใน TreeSet กัน: "

ตัวอย่าง
TreeSet<String> set = new TreeSet<String>();
Iterator<String> iterator = set.iterator();

while (iterator.hasNext())
{
 String item = iterator.next();
 System.out.println(item);
}

"การใช้ iterator แบบนี้ไม่สะดวกนัก — มีโค้ดที่ฟุ่มเฟือยและชัดเจนมากเกินไป สถานการณ์จะง่ายขึ้นเมื่อ for -eachวนซ้ำปรากฏใน Java"

"ตอนนี้รหัสนี้มีขนาดกะทัดรัดและสามารถอ่านได้มากขึ้น:"

ก่อน หลังจาก
TreeSet<String> set = new TreeSet<String>();
Iterator<String> iterator = set.iterator();

while (iterator.hasNext())
{
 String item = iterator.next();
 System.out.println(item);
}
TreeSet<String> set = new TreeSet<String>();

for(String item : set)
{
 System.out.println(item);
}

"นี่คือรหัสเดียวกัน! iterator ใช้ในทั้งสองกรณี"

"เป็นเพียงว่าการใช้งานถูกซ่อนอยู่ในfor-eachลูป โปรดทราบว่ารหัสทางด้านขวาไม่มี ข้อความ สีแดงเลย การใช้ตัววนซ้ำนั้นถูกซ่อนไว้อย่างสมบูรณ์"

" for-each loop ใช้สำหรับอ็อบเจกต์ใดๆ ที่สนับสนุนการวนซ้ำ กล่าวคือ คุณสามารถเขียนคลาสของคุณเอง เพิ่มเมธอด iterator ( )เข้าไป และใช้อ็อบเจกต์ใน โครงสร้าง for-each "

"ว้าว! แน่นอน ฉันไม่กระตือรือร้นที่จะเขียนคอลเลกชันและตัวทำซ้ำของตัวเอง แต่โอกาสยังคงดึงดูดใจ ฉันจะจดบันทึกไว้"

นอกจากนี้ยังมี iterator อีกประเภทที่ได้รับความนิยมซึ่งมีอินเทอร์เฟซของตัวเอง ฉันกำลังพูดถึงตัววนซ้ำสำหรับรายการเช่นListIterator

"โดยไม่คำนึงถึงการใช้งาน รายการจะรักษาลำดับขององค์ประกอบ ซึ่งทำให้การทำงานกับองค์ประกอบเหล่านี้ผ่าน iterator สะดวกขึ้นเล็กน้อย"

"นี่คือวิธีการของ อินเทอร์เฟซ ListIterator <E>:"

วิธี คำอธิบาย
boolean hasNext() ตรวจสอบว่ามีองค์ประกอบอื่น ๆ อีกหรือไม่
E next() ส่งกลับองค์ประกอบถัดไป
int nextIndex() ส่งกลับดัชนีขององค์ประกอบถัดไป
void set(E e) เปลี่ยนค่าขององค์ประกอบปัจจุบัน
boolean hasPrevious() ตรวจสอบว่ามีองค์ประกอบใดอยู่เบื้องหลังหรือไม่
E previous() ส่งกลับองค์ประกอบก่อนหน้า
int previousIndex() ส่งกลับดัชนีขององค์ประกอบก่อนหน้า
void remove() ลบองค์ประกอบปัจจุบัน
void add(E e) เพิ่มองค์ประกอบที่ส่วนท้ายของรายการ

"อีกนัยหนึ่ง ที่นี่เราสามารถเดินหน้าและถอยหลังได้ และยังมีฟีเจอร์เล็กๆ อีกสองสามอย่าง"

"อืม น่าสนใจดี ใช้ที่ไหน"

"สมมติว่าคุณต้องการเลื่อนไปมาในรายการที่เชื่อมโยง การดำเนินการรับจะค่อนข้างช้า แต่การดำเนินการถัดไป () จะเร็วมาก"

“อืม คุณทำให้ฉันเชื่อ ฉันจะจำมันไว้”

"ขอบคุณ เอลลี่!"