Sự khác biệt giữa Java Enumeration và Iterator


120

Sự khác biệt chính xác giữa hai giao diện này là gì? Có Enumerationlợi ích khi sử dụng Iteratorkhông? Nếu ai đó có thể giải thích, một bài báo tham khảo sẽ được đánh giá cao.


3
Tôi đã sử dụng tìm kiếm trên google và kết quả đầu tiên là một cuộc thảo luận thú vị trong JavaRanch về Enumeration vs Iterator
victor hugo

Câu trả lời:


142

Nhìn vào Đặc tả API Java cho Iteratorgiao diện, có một lời giải thích về sự khác biệt giữa Enumeration:

Trình lặp khác với liệt kê theo hai cách:

  • Các trình lặp cho phép người gọi loại bỏ các phần tử khỏi tập hợp cơ bản trong quá trình lặp với ngữ nghĩa được xác định rõ ràng.
  • Tên phương pháp đã được cải thiện.

Điểm mấu chốt là, cả hai EnumerationIteratorsẽ cung cấp các phần tử kế tiếp nhau, nhưng Iteratorđược cải tiến theo cách như vậy để tên phương thức ngắn hơn và có một removephương thức bổ sung . Đây là một so sánh song song:

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

Như đã đề cập trong Thông số kỹ thuật API của Java, đối với các chương trình mới hơn, Iteratornên được ưu tiên hơn Enumeration, vì "Iterator thay thế cho Enumeration trong khuôn khổ bộ sưu tập Java." (Từ các Iteratorthông số kỹ thuật.)


9
Tôi nghĩ rằng có một chút giải thích bị thiếu trong câu trả lời này liên quan đến đồng thời.
Maarten Bodewes

@Paul_Draper: Các chỉnh sửa không nên thêm ý nghĩa mới cho bài đăng, đó là mục đích nhận xét.
Emil

2
@coobird Bạn có chắc "Các phép liệt kê thường nhanh hơn" không? kể từ khi Enumeration có "đồng bộ hóa khối mã bên trong nextElement ()" Và Chúng tôi không có Đồng bộ hóa tại Iterator gây ra ConcurrentModificationException rit ?? Chúng tôi gọi là Trình lặp thường nhanh hơn và các phép liệt kê an toàn hơn một chút. ??
Kanagavelu Sugumar

@KanagaveluSugumar Cảm ơn bạn đã chỉ ra điều đó. (Tôi không nhận thấy rằng phần thảo luận bổ sung đã được thêm vào câu trả lời này.) Tôi đã lùi bản chỉnh sửa, vì nó không hoàn toàn chính xác.
coobird

Tôi nghĩ rằng cần chỉ ra rằng remove () là một phương thức tùy chọn trên giao diện Iterator và khá nhiều lớp triển khai không triển khai nó.
Kutzi

35

Trình lặp lại không nhanh . tức là khi một luồng thay đổi bộ sưu tập bằng các thao tác thêm / bớt, trong khi một luồng khác đang duyệt nó thông qua một hasNext() or next()phương thức sử dụng Iterator , trình vòng lặp sẽ bị lỗi nhanh chóng bằng cách ném ConcurrentModificationException. Hành vi không nhanh của trình vòng lặp chỉ có thể được sử dụng để phát hiện lỗi. Các Enumerations được trả về bởi các phương thức của các lớp như Hashtable, Vector không nhanh không đạt được bằng cách đồng bộ hóa khối mã bên trong nextElement()phương thức khóa đối tượng Vector hiện tại, tốn rất nhiều thời gian.


5
Chỉ đúng một phần: hành vi này không được xác định trong giao diện, nó phụ thuộc vào việc thực hiện của Iterator. Đúng là các triển khai bộ sưu tập 'cũ' trong java.util (HashSet, ArrayList, v.v.) thể hiện hành vi này. Tuy nhiên, các bộ sưu tập 'đồng thời' mới hơn sẽ không bao giờ ném ConcurrentModificationException, chúng sẽ duyệt qua bộ sưu tập tại thời điểm tạo trình lặp. Các triển khai khác có thể hiển thị hành vi vẫn khác.
Kutzi

1
Cũng đáng chỉ ra: "Lưu ý rằng hành vi không nhanh không thể được đảm bảo vì nói chung, không thể thực hiện bất kỳ đảm bảo cứng rắn nào khi có sửa đổi đồng thời không đồng bộ. Các hoạt động nhanh không thực hiện được ConcurrentModificationException trên cơ sở nỗ lực tối đa. Do đó , sẽ là sai lầm nếu viết một chương trình phụ thuộc vào ngoại lệ này vì tính đúng đắn của nó: ConcurrentModificationException chỉ nên được sử dụng để phát hiện lỗi. " docs.oracle.com/javase/7/docs/api/java/util/…
Kutzi

11

"Về mặt chính thức", chúng được cho là tương tự với giao diện trình lặp hỗ trợ các hoạt động bổ sung (ví dụ: loại bỏ). Nói chung, xu hướng là sử dụng các trình vòng lặp.

Đây là từ giao diện liệt kê javadocs :

LƯU Ý: Chức năng của giao diện này được sao chép bởi giao diện Iterator. Ngoài ra, Iterator thêm một thao tác loại bỏ tùy chọn và có tên phương thức ngắn hơn. Các triển khai mới nên xem xét sử dụng Iterator thay vì Enumeration.


6

Một thực tế đơn giản nhưng chưa được đề cập trong các câu trả lời trước đó là nó Iterator<T>được sử dụng với Iterable<T>để phục vụ trong for(_type_ element:collection){...}cấu trúc diễn giải .


5

Có ba điểm khác biệt cơ bản trong Enumeration và Iterator

Enumeration
1. nó chỉ được sử dụng cho lớp trễ (ví dụ. Vector)

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

2. Đọc hoạt động có thể được thực hiện, chúng tôi không thể loại bỏ phần tử.
3. Hai phương pháp có sẵn

  • public boolean hasNextElement ();
  • public Object nextElement ();

Trình lặp lại

  1. nó có thể áp dụng cho tất cả Bộ sưu tập

    Iterator itr = c.iterator();  
    where c is any `Collection` class
  2. Thao tác Đọc và Xóa có thể được thực hiện

  3. Ba phương pháp có sẵn

    • public boolean hasNext ();
    • public Object next ();
    • public void remove ();

Giới hạn ở cả hai

  • Chỉ di chuyển về phía trước
  • Không có bất kỳ phương pháp nào cho Add objectReplace object

2

Nếu bạn đang viết lớp bộ sưu tập của riêng mình và bạn đang mở rộng bất kỳ lớp nào trong số các lớp hiện có hoặc triển khai bất kỳ giao diện khung của Bộ sưu tập nào, về cơ bản bạn không có lựa chọn nào khác ngoài việc sử dụng Iterator.

Nếu vì lý do nào đó (mà tôi không thể nghĩ ra) bạn đang tạo một lớp bộ sưu tập tùy chỉnh không liên quan đến java.util.Collection hoặc java.util.Map theo bất kỳ cách nào, bạn vẫn nên triển khai Iterable để mọi người có thể sử dụng lớp của bạn trong vòng lặp for.


2

Sự khác biệt chính là Enumeration không hiển thị phương thức remove (). Hơn nữa, Iterator không cho phép điều hướng và sửa đổi đồng thời trên một đối tượng cơ bản. Họ có quyền kiểm soát để xem liệu có các sửa đổi đồng thời hay tương tự hay không, và do đó cần xử lý nhiều hơn. Vì vậy, hiệu suất của Enumeration hầu như nhanh hơn 50% so với Iterator. Nếu chúng ta chỉ cần điều hướng bỏ qua đồng bộ hóa như vậy, chỉ cần sử dụng Enumeration.


Đúng là Enumeration không "vạch trần" phương thức remove () - nhưng nó cũng không chú ý đến việc gọi ra api remove () của Collection. Ví dụ mã sau sẽ chỉ in: AAA, CCC, EEE. -------------------------------------------------- --- Vector <Chuỗi> v = new Vector <Chuỗi> (6); v.add ("AAA"); v.add ("BBB"); v.add ("CCC"); v.add ("DDD"); v.add ("EEE"); v.add ("FFF"); Enumeration <Chuỗi> en = v.elements (); while (en.hasMoreElements ()) Giá trị chuỗi = (Chuỗi) en.nextElement (); System.out.println (giá trị); v.remove (giá trị);
javauser71

1

1) Sự khác biệt chính giữa Iterator và Enumeration là loại bỏ phần tử trong khi duyệt qua bộ sưu tập. Iterator có thể loại bỏ phần tử trong quá trình duyệt bộ sưu tập vì nó có phương thức remove (). Phép liệt kê không có phương thức remove ().

2) Việc liệt kê về bản chất là không an toàn. Nó không ném ConcurrentModificationException nếu Bộ sưu tập được sửa đổi trong quá trình truyền tải. Về bản chất, Iterator không nhanh. Nó ném ConcurrentModificationException nếu một Bộ sưu tập được sửa đổi trong khi lặp khác với phương thức remove () của chính nó.

3) Enumeration là một giao diện kế thừa được sử dụng để duyệt qua Vector, Hashtable. Iterator không phải là một giao diện kế thừa. Lặp lại có thể được sử dụng để duyệt qua HashMap, LinkedList, ArrayList, HashSet, TreeMap, TreeSet.


0

Phép liệt kê chỉ có thể được sử dụng cho lớp kế thừa (Vector, Stack ...), trong khi lặp lại có thể được sử dụng cho tất cả.


-1

Cả trình lặp và liệt kê đều được sử dụng để truy xuất dữ liệu, sự khác biệt là phép liệt kê chỉ có thể được sử dụng cho các lớp kế thừa tức là vectơ / ngăn xếp trong khi các trình vòng lặp có thể được sử dụng cho phần còn lại. Phép liệt kê cũng có thể được sử dụng cho bộ khóa trong bản đồ.


Bạn đã thấy ở đâu rằng bạn có thể sử dụng Enumeration cho các tập hợp chính của Bản đồ ??
Kutzi
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.