1. ความเป็นมาเกี่ยวกับวิธีการวนซ้ำ
คุณคุ้นเคยHashSet
กับ หากคุณได้ศึกษามันจริงๆ นอกเหนือจากการอ่านบทเรียนแล้ว คุณควรถามคำถามนี้:
ฉันจะแสดงรายการองค์ประกอบ HashSet ทั้งหมดบนหน้าจอได้อย่างไร ท้ายที่สุดไม่มีอินเทอร์เฟซget()
และset()
วิธีการ!
และHashSet
ไม่ได้อยู่คนเดียวในข้อจำกัดนี้ นอกจากนี้ ยังHashSet
มีคอลเล็กชันอื่นๆ อีกมากมายที่ไม่อนุญาตให้ดึงองค์ประกอบโดยดัชนี เนื่องจากองค์ประกอบไม่มีลำดับที่กำหนดไว้
ในช่วงหลายปีที่ผ่านมา โปรแกรมเมอร์ได้คิดค้นโครงสร้างข้อมูลที่ซับซ้อนมากมาย เช่น กราฟและต้นไม้ หรือรายการของรายการ.
คอนเทนเนอร์จำนวนมากเปลี่ยนลำดับขององค์ประกอบเมื่อมีการเพิ่มองค์ประกอบใหม่หรือนำองค์ประกอบที่มีอยู่ออก ตัวอย่างเช่น รายการจัดเก็บองค์ประกอบในลำดับเฉพาะ และเมื่อมีการเพิ่มองค์ประกอบใหม่ องค์ประกอบนั้นจะถูกแทรกไว้กลางรายการเกือบตลอดเวลา
และเรายังได้รับสถานการณ์ที่มีคอนเทนเนอร์ที่เก็บองค์ประกอบ แต่ไม่ได้อยู่ในลำดับที่ตายตัว
สมมติว่าเราต้องการคัดลอกองค์ประกอบทั้งหมดจากคอลเลกชันดังกล่าวไปยังอาร์เรย์หรือรายการ เราต้องได้รับองค์ประกอบทั้งหมด เราไม่สนใจลำดับที่เราวนซ้ำองค์ประกอบต่างๆ สิ่งสำคัญคืออย่าวนซ้ำองค์ประกอบเดียวกันมากกว่าหนึ่งครั้ง เราจะทำอย่างนั้นได้อย่างไร?
2. Iterator สำหรับคอลเลกชัน
Iteratorsถูกเสนอเป็นวิธีแก้ปัญหาข้างต้น
ตัววนซ้ำเป็นวัตถุพิเศษที่เกี่ยวข้องกับคอลเลกชัน ซึ่งช่วยสำรวจองค์ประกอบทั้งหมดของคอลเลกชันโดยไม่ต้องทำซ้ำ
คุณสามารถใช้รหัสต่อไปนี้เพื่อรับตัววนซ้ำสำหรับคอลเลกชันใดๆ:
Iterator<Type> it = name.iterator();
โดยที่name
ชื่อของตัวแปรคอลเล็กชันType
คือประเภทขององค์ประกอบของคอลเล็กชันiterator()
เป็นหนึ่งในเมธอดของคอลเล็กชัน และit
เป็นชื่อของตัวแปรวนซ้ำ
ตัววนซ้ำมี 3 วิธี:
วิธี | คำอธิบาย |
---|---|
|
ส่งกลับองค์ประกอบถัดไปในคอลเลกชัน |
|
ตรวจสอบว่ามีองค์ประกอบใดบ้างที่ยังไม่ได้สำรวจ |
|
ลบองค์ประกอบปัจจุบันของคอลเลกชัน |
เมธอดเหล่านี้ค่อนข้างคล้ายกับคลาสnextInt)
และhasNextInt()
วิธีการ ของ Scanner
เมธอดnext()
ส่งคืนองค์ประกอบถัดไปของคอลเลกชันที่เราได้รับตัววนซ้ำ
เมธอดhasNext()
ตรวจสอบว่าคอลเล็กชันมีองค์ประกอบเพิ่มเติมที่ตัววนซ้ำยังไม่ส่งคืนหรือไม่
นี่คือวิธีแสดงองค์ประกอบทั้งหมดของ a HashSet
:
รหัส | หมายเหตุ |
---|---|
|
สร้างHashSet วัตถุที่เก็บString องค์ประกอบ เราเพิ่มคำทักทายในภาษาต่างๆ ให้กับ set ตัวแปร รับตัววนซ้ำวัตถุสำหรับ set ชุด ตราบใดที่ยังมีองค์ประกอบ รับองค์ประกอบถัดไป แสดงองค์ประกอบบนหน้าจอ |
3. For-each
วนซ้ำ
ข้อเสียเปรียบหลักของตัววนซ้ำคือโค้ดของคุณจะยุ่งยากกว่าการใช้for
ลูป
ในการเปรียบเทียบ ลองแสดงรายการโดยใช้for
การวนซ้ำและใช้ตัววนซ้ำ:
วนซ้ำ | สำหรับลูป |
---|---|
|
|
ใช่ มันจะดีกว่ามากที่จะสำรวจองค์ประกอบของArrayList
การใช้ลูป — ทุกอย่างจะสั้นลง
แต่ผู้สร้างของ Java ตัดสินใจเทน้ำตาลใส่เราอีกครั้ง โชคดีสำหรับเรา มันเป็นน้ำตาลวากยสัมพันธ์
พวกเขาสร้างลูปชนิดใหม่ให้กับ Java และเรียกมันว่าfor-each
ลูป นี่คือลักษณะโดยทั่วไป:
for(Type name:collection)
โดยที่collection
ชื่อของตัวแปรคอลเล็กชันType
คือประเภทขององค์ประกอบในคอลเล็กชัน และname
เป็นชื่อของตัวแปรที่รับค่าถัดไปจากคอลเล็กชันในการวนซ้ำแต่ละครั้ง
การวนซ้ำประเภทนี้จะวนซ้ำองค์ประกอบทั้งหมดของคอลเล็กชันโดยใช้ตัววนซ้ำโดยปริยาย นี่คือวิธีการทำงานจริง:
สำหรับแต่ละวง | สิ่งที่คอมไพเลอร์เห็น: วนซ้ำด้วยตัววนซ้ำ |
---|---|
|
|
เมื่อคอมไพเลอร์พบfor-each
การวนซ้ำในโค้ดของคุณ ก็จะแทนที่ด้วยโค้ดทางด้านขวา: จะเพิ่มการเรียกใช้เพื่อรับตัววนซ้ำพร้อมกับการเรียกเมธอดอื่นๆ ที่ขาดหายไป
โปรแกรมเมอร์ชอบfor-each
ลูปและมักจะใช้มันเมื่อต้องการวนซ้ำองค์ประกอบทั้งหมดของคอลเลกชัน
แม้แต่การวนซ้ำArrayList
รายการโดยใช้for-each
การวนซ้ำก็ยังดูสั้นกว่า:
สำหรับแต่ละวง | สำหรับลูป |
---|---|
|
|
4. การลบองค์ประกอบในfor-each
ลูป
ลูfor-each
ปมีข้อเสียอย่างหนึ่ง: ไม่สามารถลบองค์ประกอบได้อย่างถูกต้อง หากคุณเขียนโค้ดแบบนี้ คุณจะได้รับข้อผิดพลาด
รหัส | บันทึก |
---|---|
|
การดำเนินการลบจะทำให้เกิดข้อผิดพลาด! |
นี่เป็นรหัสที่ดีและเข้าใจได้ แต่มันใช้งานไม่ได้
คุณไม่สามารถเปลี่ยนคอลเลกชั่นได้ในขณะที่คุณกำลังสำรวจมันด้วยตัววนซ้ำ
มีสามวิธีในการหลีกเลี่ยงข้อจำกัดนี้
1. ใช้ลูปประเภทอื่น
When traversing an ArrayList collection
คุณสามารถใช้ลูปธรรมดากับตัวแปรi
ตัวนับได้
รหัส |
---|
|
อย่างไรก็ตามตัวเลือกนี้ไม่เหมาะสำหรับHashSet
คอHashMap
ลเลกชัน
2. ใช้ตัววนซ้ำที่ชัดเจน
คุณสามารถใช้ iterator อย่างชัดเจนและเรียกremove()
เมธอด ของมัน
รุ่นที่ใช้งาน | เวอร์ชันที่ใช้งานไม่ได้ |
---|---|
|
|
โปรดทราบว่าเราเรียกremove()
เมธอดบน iterator object! ตัววนซ้ำทราบว่ารายการถูกลบแล้วและสามารถจัดการกับสถานการณ์ได้อย่างถูกต้อง
3. ใช้สำเนาของคอลเลกชัน
คุณยังสามารถสร้างสำเนาของคอลเลกชัน จากนั้นใช้สำเนาในลูfor-each
ปและลบองค์ประกอบออกจากคอลเลกชันต้นฉบับ
รหัส | บันทึก |
---|---|
|
การสร้างสำเนาของคอลเลกชันนั้นง่ายมาก การวนซ้ำจะใช้ตัววนซ้ำสำหรับสำเนาของคอลเลกชัน องค์ประกอบจะถูกลบออกจาก list คอลเลกชัน |
คอลเลกชันถูกคัดลอกค่อนข้างเร็วเนื่องจากองค์ประกอบไม่ได้ซ้ำกัน คอลเลกชันใหม่จะเก็บการอ้างอิงถึงองค์ประกอบที่มีอยู่แล้วในคอลเลกชันเก่าแทน
GO TO FULL VERSION