ความแตกต่างระหว่าง Java Enumeration และ Iterator


120

อะไรคือความแตกต่างที่แน่นอนระหว่างสองอินเทอร์เฟซนี้? ไม่Enumerationมีประโยชน์มากกว่าการใช้Iterator? หากใครสามารถอธิบายได้อย่างละเอียดบทความอ้างอิงจะได้รับการชื่นชม


3
ฉันใช้การค้นหาโดย Google และผลลัพธ์แรกคือการสนทนาที่น่าสนใจใน JavaRanch เกี่ยวกับEnumeration vs Iterator
victor hugo

คำตอบ:


142

ดูข้อกำหนด Java API สำหรับIteratorอินเทอร์เฟซมีคำอธิบายเกี่ยวกับความแตกต่างระหว่างEnumeration:

ตัวทำซ้ำแตกต่างจากการแจงนับในสองวิธี:

  • ตัวทำซ้ำอนุญาตให้ผู้เรียกลบองค์ประกอบออกจากคอลเลกชันที่อยู่เบื้องหลังระหว่างการวนซ้ำด้วยความหมายที่กำหนดไว้อย่างดี
  • ปรับปรุงชื่อเมธอดแล้ว

บรรทัดล่างคือทั้งสองอย่างEnumerationและIteratorจะให้องค์ประกอบที่ต่อเนื่องกัน แต่Iteratorได้รับการปรับปรุงในลักษณะนี้ดังนั้นชื่อวิธีการจึงสั้นลงและมีremoveวิธีการเพิ่มเติม นี่คือการเปรียบเทียบแบบเคียงข้างกัน:

  Enumeration                     Iterator
  ----------------                ----------------
  hasMoreElement()                hasNext()
  nextElement()                   next()
  N/A                             remove()

ตามที่กล่าวไว้ในข้อกำหนด Java API สำหรับโปรแกรมใหม่ ๆIteratorควรเป็นที่ต้องการมากกว่าEnumerationเนื่องจาก "Iterator ใช้แทน Enumeration ในกรอบงานคอลเลกชัน Java" (จากIteratorข้อมูลจำเพาะ)


9
ฉันคิดว่ามีคำอธิบายเล็กน้อยที่ขาดหายไปจากคำตอบนี้เกี่ยวกับการทำงานพร้อมกัน
Maarten Bodewes

@Paul_Draper: การแก้ไขไม่ควรเพิ่มความหมายใหม่ให้กับโพสต์นั่นคือสิ่งที่แสดงความคิดเห็น
Emil

2
@coobird แน่ใจหรือว่า "โดยทั่วไปแล้วการแจงนับจะเร็วกว่า" เนื่องจาก Enumeration มี "การซิงโครไนซ์บล็อกของโค้ดภายใน nextElement ()" และเราไม่มีการซิงโครไนซ์ที่ Iterators ซึ่งทำให้เกิด ConcurrentModificationException rit ?? เราเรียกว่า Iterators โดยทั่วไปแล้วจะเร็วกว่าและ Enumerations จะปลอดภัยกว่าเล็กน้อย ??
Kanagavelu Sugumar

@KanagaveluSugumar ขอบคุณที่ชี้ให้เห็น (ฉันไม่ได้สังเกตว่ามีการเพิ่มการสนทนาเพิ่มเติมในคำตอบนี้) ฉันย้อนกลับการแก้ไขแล้วเนื่องจากมันไม่ถูกต้องทั้งหมด
coobird

ฉันคิดว่ามันคุ้มค่าที่จะชี้ให้เห็นว่าการลบ () เป็นวิธีการทางเลือกบนอินเทอร์เฟซ Iterator และคลาสที่ใช้งานค่อนข้างมากไม่ได้นำไปใช้
Kutzi

35

Iterators จะล้มเหลวได้อย่างรวดเร็ว เช่นเมื่อหนึ่งในหัวข้อการเปลี่ยนแปลงการเก็บรวบรวมจากการดำเนินงานเพิ่ม / ลบในขณะที่หัวข้ออื่น traversing มันผ่าน Iterator โดยใช้hasNext() or next()วิธี iterator ConcurrentModificationExceptionล้มเหลวได้อย่างรวดเร็วโดยการขว้างปา พฤติกรรมที่ล้มเหลวอย่างรวดเร็วของตัวทำซ้ำสามารถใช้เพื่อตรวจหาจุดบกพร่องเท่านั้น การแจงนับที่ส่งคืนโดยวิธีการของคลาสเช่น Hashtable, Vector ไม่ใช่การทำงานอย่างรวดเร็วที่ทำได้โดยการซิงโครไนซ์บล็อกของโค้ดภายในnextElement()วิธีการที่ล็อกอ็อบเจ็กต์ Vector ปัจจุบันซึ่งใช้เวลามาก


5
เป็นจริงเพียงบางส่วนเท่านั้น: พฤติกรรมนี้ไม่ได้กำหนดไว้ในอินเทอร์เฟซ แต่ขึ้นอยู่กับการใช้งาน Iterator เป็นความจริงที่การใช้งานคอลเลกชัน 'เก่า' ใน java.util (HashSet, ArrayList และอื่น ๆ ) แสดงพฤติกรรมนี้ อย่างไรก็ตามคอลเลกชัน 'พร้อมกัน' ที่ใหม่กว่าจะไม่โยน ConcurrentModificationException พวกเขาจะสำรวจคอลเลกชัน ณ เวลาที่สร้างตัววนซ้ำ การใช้งานอื่น ๆ อาจแสดงพฤติกรรมที่แตกต่างออกไป
Kutzi

1
นอกจากนี้ยังชี้ให้เห็นว่า: "โปรดทราบว่าพฤติกรรมที่ล้มเหลวอย่างรวดเร็วไม่สามารถรับประกันได้ตามที่เป็นอยู่โดยทั่วไปแล้วเป็นไปไม่ได้ที่จะทำการรับประกันอย่างหนักหน่วงใด ๆ เมื่อมีการปรับเปลี่ยนพร้อมกันที่ไม่ซิงโครไนซ์การดำเนินการที่รวดเร็วล้มเหลวทำให้เกิด ConcurrentModificationException ด้วยความพยายามอย่างดีที่สุดดังนั้น การเขียนโปรแกรมที่ขึ้นอยู่กับข้อยกเว้นนี้เพื่อความถูกต้องอาจเป็นเรื่องผิด: ควรใช้ ConcurrentModificationException เพื่อตรวจหาจุดบกพร่องเท่านั้น " docs.oracle.com/javase/7/docs/api/java/util/…
Kutzi

11

"อย่างเป็นทางการ" ซึ่งควรจะคล้ายกับอินเทอร์เฟซตัววนซ้ำที่รองรับการดำเนินการเพิ่มเติม (เช่นการลบ) โดยทั่วไปมีแนวโน้มที่จะใช้ตัวทำซ้ำ

นี่คือจากjavadocs อินเทอร์เฟซการแจงนับ :

หมายเหตุ: การทำงานของอินเทอร์เฟซนี้ซ้ำกันโดยอินเทอร์เฟซ Iterator นอกจากนี้ Iterator ยังเพิ่มการดำเนินการลบที่เป็นทางเลือกและมีชื่อวิธีการที่สั้นกว่า การใช้งานใหม่ควรพิจารณาใช้ Iterator ตามความต้องการของ Enumeration


6

ข้อเท็จจริงง่ายๆอย่างหนึ่ง แต่ไม่ได้กล่าวถึงในคำตอบก่อนหน้านี้Iterator<T>คือใช้Iterable<T>เพื่อทำหน้าที่ในการตีความfor(_type_ element:collection){...}โครงสร้าง


5

มีความแตกต่างพื้นฐานสามประการในการแจงนับและตัวทำซ้ำ

การแจงนับ
1. ใช้สำหรับคลาส lagacy เท่านั้น (เช่นVector)

    Enumeration e = v.elements();  
    v is the object of `Vector` class

2. สามารถดำเนินการอ่านได้เราไม่สามารถลบองค์ประกอบได้
3. มีสองวิธี

  • บูลีนสาธารณะ hasNextElement ();
  • วัตถุสาธารณะ nextElement ();

iterator

  1. ใช้ได้กับคอลเลคชันทั้งหมด

    Iterator itr = c.iterator();  
    where c is any `Collection` class
  2. สามารถดำเนินการอ่านและลบได้

  3. มีสามวิธี

    • บูลีนสาธารณะ hasNext ();
    • วัตถุสาธารณะต่อไป ();
    • โมฆะสาธารณะลบ ();

ข้อ จำกัดในทั้งสองอย่าง

  • เดินหน้าไปข้างหน้าเท่านั้น
  • ไม่มีวิธีการใด ๆ สำหรับAdd objectและReplace object

2

หากคุณกำลังเขียนคลาสคอลเลกชันของคุณเองและคุณกำลังขยายคลาสที่มีอยู่หรือใช้อินเทอร์เฟซกรอบงานคอลเลคชันใด ๆ โดยพื้นฐานแล้วคุณจะไม่มีทางเลือกอื่นนอกจากใช้ Iterator

หากมีเหตุผลบางคน (ที่ผมไม่สามารถคิด) คุณกำลังสร้างชั้นคอลเลกชันที่กำหนดเองที่ไม่เกี่ยวข้องกับ java.util.Collection หรือ java.util.Map ในทางใด ๆ ที่คุณควรจะยังคงดำเนินการ Iterable เพื่อให้ประชาชนสามารถใช้ ชั้นเรียนของคุณสำหรับลูป


2

ข้อแตกต่างที่สำคัญคือการแจงนับไม่แสดงวิธีลบ () ยิ่งไปกว่านั้น Iterator ไม่อนุญาตการนำทางพร้อมกันและการแก้ไขบนวัตถุที่อยู่เบื้องหลัง พวกเขามีการควบคุมเพื่อดูว่ามีการแก้ไขพร้อมกันหรือไม่และด้วยเหตุนี้จึงต้องใช้การประมวลผลมากขึ้น ดังนั้นประสิทธิภาพของ Enumeration จึงเร็วกว่า Iterator เกือบ 50% หากเราต้องการเพียงการนำทางโดยไม่สนใจการซิงโครไนซ์ดังกล่าวให้ใช้การแจงนับ


เป็นความจริงที่ว่า Enumeration จะ "ไม่" เปิดเผยเมธอด remove () แต่ก็ไม่ได้ใส่ใจกับการเรียกใช้ api remove () ของ Collection ตัวอย่างเช่นโค้ดต่อไปนี้จะพิมพ์ออกมา: AAA, CCC, EEE -------------------------------------------------- - Vector <String> v = Vector ใหม่ <String> (6); v.add ( "AAA"); v.add (ระดับ "BBB"); v.add ( "CCC"); v.add ( "DDD"); v.add ( "EEE"); v.add ( "FFF"); การแจงนับ <String> th = v.elements (); ในขณะที่ (en.hasMoreElements ()) ค่าสตริง = (สตริง) en.nextElement (); System.out.println (คุ้มค่า); v.remove (คุ้มค่า);
javauser71

1

1) ความแตกต่างที่สำคัญระหว่าง Iterator และ Enumeration คือการนำองค์ประกอบออกในขณะที่ข้ามคอลเลกชัน Iterator สามารถลบองค์ประกอบในระหว่างการข้ามคอลเลกชันได้เนื่องจากมีวิธีการลบ () การแจงนับไม่มีวิธีลบ ()

2) การแจงนับไม่ปลอดภัยโดยธรรมชาติ จะไม่โยน ConcurrentModificationException หากคอลเลกชันถูกแก้ไขในระหว่างการส่งผ่าน Iterator นั้นล้มเหลวอย่างรวดเร็วโดยธรรมชาติ มันพ่น ConcurrentModificationException หากคอลเลกชันถูกแก้ไขในขณะที่ทำซ้ำวิธีอื่นที่ไม่ใช่เมธอด remove () ของตัวเอง

3) การแจงนับเป็นอินเทอร์เฟซแบบเดิมที่ใช้สำหรับการข้ามผ่าน Vector, Hashtable Iterator ไม่ใช่อินเทอร์เฟซเดิม Iterator สามารถใช้สำหรับการข้ามผ่านของ HashMap, LinkedList, ArrayList, HashSet, TreeMap, TreeSet


0

การแจงนับสามารถใช้ได้กับคลาสเดิมเท่านั้น (Vector, Stack ... ) ในขณะที่ Iterator สามารถใช้ได้กับทุกคน


-1

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


คุณเห็นว่าคุณสามารถใช้การแจงนับสำหรับชุดคีย์ของแผนที่ได้ที่ไหน ??
Kutzi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.