2012-06-24 69 views
22

Nói rằng tôi có một danh sách như:Làm cách nào để thêm phần tử vào Danh sách khi đang lặp trong java?

List<String> list = new ArrayList<>(); 
list.add("a"); 
list.add("h"); 
list.add("f"); 
list.add("s"); 

Trong khi lặp qua danh sách này, tôi muốn thêm một phần tử ở cuối danh sách. Nhưng tôi không muốn lặp qua các phần tử mới được thêm vào mà tôi muốn lặp lại với kích thước ban đầu của danh sách.

for (String s : list) 
    /* Here I want to add new element if needed while iterating */ 

Ai có thể đề xuất tôi làm cách nào tôi có thể thực hiện việc này?

Trả lời

32

Bạn không thể sử dụng tuyên bố foreach cho điều đó. Các foreach được sử dụng trong nội bộ một iterator:

các vòng lặp được trả về bởi iterator của lớp này và listIterator phương pháp này 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 nào ngoại trừ thông qua các phương thức xóa hoặc thêm của riêng trình tự của vòng lặp , trình lặp sẽ ném một ConcurrentModificationException.

(Từ ArrayList javadoc)

Trong tuyên bố foreach bạn không có quyền truy cập vào phương thức add của iterator và trong bất kỳ trường hợp đó vẫn không phải là loại add mà bạn muốn vì nó không nối thêm tại kết thúc. Bạn cần phải duyệt danh sách theo cách thủ công:

int listSize = list.size(); 
for(int i = 0; i < listSize; ++i) 
    list.add("whatever"); 

Lưu ý rằng điều này chỉ hiệu quả đối với Danh sách cho phép truy cập ngẫu nhiên. Bạn có thể kiểm tra tính năng này bằng cách kiểm tra xem danh sách có triển khai giao diện điểm đánh dấu RandomAccess hay không. An ArrayList có quyền truy cập ngẫu nhiên. Một danh sách liên kết thì không.

1

Bạn có thể lặp lại trên một bản sao (clone) của danh sách ban đầu của bạn:

List<String> copy = new ArrayList<String>(list); 
for (String s : copy) { 
    // And if you have to add an element to the list, add it to the original one: 
    list.add("some element"); 
} 

Lưu ý rằng nó không phải là thậm chí có thể thêm một yếu tố mới vào danh sách, trong khi lặp lại trên nó, bởi vì nó sẽ gây ra a ConcurrentModificationException.

8

Chỉ cần lặp theo cách cũ thời trang, bởi vì bạn cần xử lý chỉ số rõ ràng:

List myList = ... 
... 
int length = myList.size(); 
for(int i = 0; i < length; i++) { 
    String s = myList.get(i); 
    // add items here, if you want to 
} 
+1

Không, nó sẽ không.Nó sẽ khi sử dụng một trình lặp và thêm các bổ sung trong khi lặp lại, nhưng không phải khi thực hiện lặp lại một mình ở đây. –

+0

OPs muốn "lặp lại kích thước nội bộ". –

+0

Doh! Đọc kém phần của tôi. –

0

Tôi làm điều này bằng cách thêm các yếu tố để một, Danh sách tmp trống mới , sau đó thêm danh sách tmp vào danh sách ban đầu bằng cách sử dụng addAll(). Điều này ngăn không cần sao chép một danh sách nguồn lớn.

Hãy tưởng tượng điều gì xảy ra khi danh sách ban đầu của OP có vài triệu mục trong đó; trong một thời gian bạn sẽ hút xuống gấp đôi bộ nhớ.

Ngoài việc bảo tồn tài nguyên, kỹ thuật này cũng ngăn không cho chúng ta phải sử dụng kiểu vòng 80 cho các vòng lặp và sử dụng các chỉ mục mảng hiệu quả có thể không hấp dẫn trong một số trường hợp.

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