2013-04-14 38 views
29

Tôi đã đọc câu trả lời được đề cập đến câu hỏi "Do we ever need to use Iterators on ArrayList?".Tại sao chúng ta cần sử dụng trình lặp trên ArrayList trong Java?

Trong câu trả lời, người dùng đã tuyên bố một cái gì đó như thế này: "Một trường hợp sử dụng lớn các trình vòng lặp với ArrayLists là khi bạn muốn loại bỏ các phần tử trong khi lặp lại".

Điều này có thể đạt được ngay cả khi sử dụng phương pháp xóa ArrayList trong Java. Câu hỏi của tôi là tại sao chúng ta cần iterator trong ArrayList?

xem xét mã:

import java.util.*; 
public class ocajp66 { 
    public static void main(String[] args) { 
     ArrayList a = new ArrayList(); 
     for (int i = 0; i < 10; i++) { 
      a.add(i); 
     } 
     System.out.printf("BEFORE ITERATOR\n"); 
     for (int i = 0; i < a.size(); i++) { 
      System.out.printf("I:%d\n", a.get(i)); 
     } 
     System.out.printf("AFTER ITERATOR\n"); 
     Iterator i = a.iterator(); 
     while (i.hasNext()) { 
      System.out.printf("I:%d\n", i.next()); 
     } 
    } 
} 

Ai có thể giải thích ý nghĩa của các iterator? Thật tuyệt vời nếu bạn có thể giải thích cho tôi bằng mã.

+0

"Điều này có thể đạt được ngay cả khi sử dụng phương pháp xóa ArrayList trong java". Bạn đã thử cái này chưa? – kosa

+1

Câu hỏi này khác với câu hỏi được liên kết như thế nào? – Howard

+0

@Nambari là người khởi xướng trong java tôi muốn biết ý nghĩa của trình lặp trong java tại sao chúng ta cần nó khi có thể sửa đổi/xóa/chèn bằng vòng lặp –

Trả lời

47

Như bạn đã nói trình lặp được sử dụng khi bạn muốn loại bỏ nội dung trong khi bạn lặp qua nội dung mảng. Nếu bạn không sử dụng một iterator nhưng chỉ đơn giản là có một vòng lặp for và bên trong nó sử dụng phương thức remove, bạn sẽ nhận được các ngoại lệ vì các nội dung của mảng thay đổi trong khi bạn lặp qua. ví dụ: bạn có thể nghĩ kích thước mảng là 10 khi bắt đầu vòng lặp nhưng nó sẽ không là trường hợp khi bạn xóa nội dung .. vì vậy khi u đạt đến vòng cuối cùng có thể sẽ có IndexOutofBoundsException v.v.

+1

Đây không phải là câu trả lời đúng. Iterator là một cách để gói gọn các mảng để bạn không thể chỉnh sửa nội dung của chúng. Những gì bạn đang nói về đã được thêm vào vòng lặp sau này. – David

+1

đó là lý do tại sao bạn sử dụng array.size() cho điều kiện vòng lặp for và không phải là số ma thuật. –

12

Rõ ràng là một API giống như ArrayList có thể hoạt động mà không cần phương thức iterator(). Tuy nhiên, ArrayListCollection và phương pháp iterator() được xác định trong giao diện Collection ... do đó ArrayList để triển khai.

Điểm về việc xóa từ một ArrayList là làm nó bằng cách lập chỉ mục đòi hỏi một số suy nghĩ:

for (int i = 0; 
     i < a.size(); // Hoist this at your peril 
     i++) { 
     if (a.get(i) == something) { 
      a.remove(i); 
      i--; // Leave this out at your peril 
     } 
    } 

Và nó sẽ nặng hơn nếu bạn cần phải loại bỏ các yếu tố danh sách trong một phương pháp gọi là từ vòng ... 'cos phương pháp phải sau đó nói rằng nó đã loại bỏ một phần tử để người gọi có thể điều chỉnh chỉ số vòng lặp.

Lý do thứ ba tại sao iterator là một điều tốt trên ArrayList là nó cho phép bạn sử dụng cú pháp for (type var : iterable) ... của Java 5.

Điểm mấu chốt là bạn không phải sử dụng trình lặp trên ArrayList trường hợp. Nếu bạn không muốn, thì đừng.

+0

Bạn có thể sử dụng ký hiệu vòng lặp đó trên ArrayList trực tiếp; trình vòng lặp không cần thiết. Việc xóa các phần tử trong quá trình truyền tải là lý do duy nhất. Nó sẽ được mát mẻ để có một ArrayList với một điểm đánh dấu loại bỏ bằng cách nào đó loại bỏ tất cả các yếu tố được đánh dấu ở cuối vòng lặp. Một người đàn ông có thể mơ ước :) –

+0

Ngoại trừ việc sửa đổi biến lặp được coi là một thực hành không tốt và bạn sẽ không bao giờ làm điều đó. – pseudo

+0

@pseudo - điều đó đúng, nhưng tôi không hiểu tại sao bạn lại nhắc đến nó ở đây. Là câu trả lời của tôi hoặc bất kỳ ý kiến ​​* đề xuất * rằng mọi người nên sửa đổi các biến vòng lặp ?? –

1

Hỏi: Tại sao chúng ta cần trình lặp trong ArrayList?

Chúng tôi không - giống như bạn đã thể hiện trong mã của mình, bạn có thể lặp lại và thực hiện các phép toán lõi trên ArrayList mà không có trình lặp. Nhưng thật tuyệt khi có tính năng.

Q: Ai có thể giải thích ý nghĩa của trình lặp không?

Ngoài giá trị thiết kế, tôi có thể thấy là tính năng không nhanh của nó.Tôi trích đoạn này từ ArrayList documentation:

Các vòng lặp được trả về bởi iterator và của lớp này listIterator phương pháp thất bại nhanh: nếu danh sách được cấu trúc biến đổi bất cứ lúc nào sau khi iterator được tạo ra, trong bất kỳ cách ngoại trừ thông qua phương pháp loại bỏ hoặc thêm phương thức riêng của một trình lặp, thì trình vòng lặp sẽ ném một số ConcurrentModificationException. Do đó, khi đối mặt với sửa đổi đồng thời, trình vòng lặp không nhanh chóng và sạch sẽ, thay vì rủi ro hành vi tùy ý, không xác định tại thời điểm chưa xác định trong tương lai.

Bạn đang tìm mã, bạn thực sự có thể xem triển khai trình lặp của ArrayList tại đây: ArrayList.java.

+0

Có điều gì đặc biệt trong câu trả lời của bạn yêu cầu sử dụng phông chữ lớn này ? – Vitaly

+0

Có bạn đi, làm cho nó nhỏ hơn. – Jops

6

Đây là ví dụ về cách có thể nhận được kết quả bạn muốn theo nhiều cách khác nhau. Kiểu dự phòng này không phải là duy nhất đối với Java.

  • for (int i = 0; i < myArray.length; i ++) {...}

Cú pháp này đã được giới thiệu trong phiên bản rất sớm của Java. Nó lặp qua một mảng Java thông thường trong một vòng lặp for {}. Điều này nói chung là an toàn vì các mảng Java có chiều dài cố định và vì vậy không thể có ngoại lệ "Chỉ số ngoài giới hạn".

  • for (int i = 0; i < myArrayList.size(); i ++ {...}

Cú pháp này phản ánh một thông cáo sau này của Java, sau sự ra đời của API Collections mà Các lớp thực hiện giao diện Collection, như đã đề cập ở trên, phải thực hiện một Iterator nhưng bạn không cần phải sử dụng nó.Điều này cho {} loop không, nhưng nguy hiểm ở đây là ArrayLists không có kích thước cố định. Nếu nó co lại trong cơ thể của vòng lặp for của bạn, và ngoại lệ có thể dẫn đến.

  • cho (MyArrayType t: myArrayList) {}

Cú pháp này cũng được phát hành trong phiên bản sau của Java. Nó được gọi là vòng lặp nâng cao. Bất kỳ lớp sưu tập nào cung cấp Iterator bằng cách triển khai giao diện Iterable đều có thể tận dụng cú pháp này. Điều này cho phép lặp qua các mục trong một bộ sưu tập mà không cần phải khởi tạo một Iterator một cách rõ ràng. Một cách ưa thích để sử dụng điều này trong một ứng dụng JavaFX là lặp qua một loạt các điều khiển để thiết lập một thuộc tính cho một giá trị, ví dụ. để thiết lập lại các nội dung của một nhóm các Trường văn bản:

for (TextField tf : new TextField[] { txtf1, txtf2, txtf3, txtfa, txtfb, txtfc}) { 
    tf.setText(""); 
} 
  • while (myCollectionIterator.hasNext()) {}

Bạn luôn có thể nhanh chóng một cách rõ ràng một Iterator. Điều này là an toàn để sử dụng khi kích thước bộ sưu tập đang thay đổi (từ các phương thức riêng của Bộ sưu tập). Nó đúng để nói rằng Iterator là chặt chẽ hơn một tài sản của giao diện Iterable hơn là một tính năng của ngôn ngữ Java lõi. Nhưng bạn vẫn có thể sử dụng nó như một tính năng giống như ngôn ngữ (trong vòng lặp nâng cao) nhờ các phiên bản Java sau này.

Các cấu trúc này cung cấp dự phòng nhưng chúng không giống nhau. Có những sắc thái của mỗi cái cho phép một đặc biệt hữu ích tại một thời điểm nhất định. Bạn nên sử dụng tất cả chúng.

+0

Cảm ơn bạn đã thông báo hữu ích –

0

Đối với câu hỏi của bạn, nếu chúng tôi sử dụng phương pháp list.remove() thay vì iterator.remove() thì IndexOutOfBoundsException sẽ bị ném.

list.remove() là an toàn để sử dụng nếu bạn đặt break tuyên bố một khi bạn tìm thấy đối tượng cụ thể/index phải được loại bỏ để nó sẽ được thoát khỏi vòng lặp mà không cần bất kỳ ngoại lệ (như IndexOutOfBoundsException)

Sau đang iterator vẫn có thể némConcurrentModificationException nếu chúng tôi sử dụng lặp EVEN trong đồng bộ hóa môi trường.

List<String> empNames = new ArrayList<String>(); 
     synchronized (empNames) { 
      Iterator<String> iterator = empNames.iterator(); 
      while (iterator.hasNext()) { 
       iterator.next(); 
       empNames.add("Another Name"); // throws 
       // ConcurrentModificationException 
      } 
     } 
+0

lý do tại sao chúng tôi gặp lỗi IndexOutOfBoundsException nếu chúng tôi sử dụng list.remove()? – JAVA

Các vấn đề liên quan