2008-11-18 5 views
9

Giả sử tôi có một đối tượng Listmột trình lặp số cho danh sách đó.Khi tôi sắp xếp một Danh sách những gì xảy ra với các trình lặp của nó?

Bây giờ tôi sắp xếp danh sách với java.util.Collections.sort()

  • gì xảy ra với iterator?
  • Hành vi của nó vẫn được xác định và nó vẫn có thể được sử dụng?
  • Nếu không, tôi có thể ngăn việc hủy các trình vòng lặp cho danh sách không?

Tôi biết, vấn đề này có thể bị phá vỡ bằng cách thay đổi thiết kế chương trình, nhân bản danh sách ví dụ, nhưng tôi đặc biệt muốn biết hành vi "chính thức" của Java.

Trả lời

15

Hầu hết các bộ sưu tập trong java.util là "không nhanh" và có thể ném ConcurrentModificationException nếu bộ sưu tập cơ bản bị thay đổi. Nó nên được chỉ ra rằng điều này là dành cho gỡ lỗi và do đó không được bảo đảm. Theo javadocs, điều này đúng với tất cả các số tiền của AbstractList, nhưng đây là không đúng của CopyOnWriteArrayList, được thiết kế để sử dụng đa luồng.

17

Bộ lặp thường không hợp lệ sau khi sửa đổi bất kỳ nào thành bộ sưu tập cơ bản của chúng, ngoại trừ thông qua bản thân trình lặp. (Ví dụ: ListIterator cho phép chèn và xóa.)

Tôi chắc chắn mong đợi bất kỳ trình vòng lặp nào bị vô hiệu hóa sau một sắp xếp - và nếu không, tôi không biết nên mong đợi điều gì.

+0

Câu trả lời rõ ràng cho một trình lặp đơn 'p' trỏ vào bộ sưu tập' c'. Điều gì về việc có hai vòng lặp 'p' và' q' trỏ vào cùng một bộ sưu tập 'c' và được lặp lại độc lập? Liệu _ "ngoại trừ thông qua bản thân trình lặp" _ có nghĩa là cá thể cụ thể của trình lặp như 'p' hay nó có nghĩa là bất kỳ cá thể nào của trình lặp? Tôi đoán việc lặp lại độc lập 'p' và' q' sẽ làm mất hiệu lực lẫn nhau (đơn giản vì không có trình lặp nào biết về các trình vòng lặp khác cũng như bộ nhớ nhớ tất cả các trình vòng lặp của nó), nhưng tốt nhất là làm rõ nó ở đây. Cảm ơn! – uvsmtid

+1

@uvsmtid: Ngoại trừ thông qua trình lặp cụ thể đó. Nếu bạn có hai trình vòng lặp trên cùng một bộ sưu tập, thì bạn không thể sửa đổi bộ sưu tập qua một trong hai bộ sưu tập đó, trừ khi đó là bộ sưu tập hỗ trợ rõ ràng đồng thời sửa đổi. –

4

Nói chung, bất kỳ loại đột biến nào trên bộ sưu tập sẽ làm mất hiệu lực trình lặp của nó. Một đột biến được thực hiện thông qua một trình lặp sẽ không làm mất hiệu lực trình lặp đó. Có một số triển khai bộ sưu tập đặc biệt, chẳng hạn như CopyOnWriteArrayList.

Giải pháp chung là sắp xếp một bản sao của bộ sưu tập hoặc tạo lại các trình lặp của bạn.

2

Tôi đã viết một số mã để xem điều gì xảy ra khi một bộ sưu tập được sắp xếp trong khi bạn đang lặp lại. Dường như các iterator không ném bất kỳ trường hợp ngoại lệ, nhưng vẫn tiếp tục lặp lại bình thường. Tuy nhiên nó sẽ cho bạn kết quả sai nếu bạn đang mong đợi để lặp qua bộ sưu tập chưa được phân loại. Nhìn vào đó:

public static void main(String[] args) { 
    List<String> list = new ArrayList<String>(); 
    list.add("D"); 
    list.add("B"); 
    list.add("A"); 
    list.add("C"); 
    list.add("E"); 

    Iterator<String> it = list.iterator(); 
    String s = it.next(); 
    System.out.println(s); 
    s = it.next(); 
    System.out.println(s); 

    Collections.sort(list); 
    Iterator<String> it2 = list.iterator(); 

    s = it.next(); 
    System.out.println(s); 
    s = it.next(); 
    System.out.println(s); 
    s = it.next(); 
    System.out.println(s); 

    while (it2.hasNext()) { 
     System.out.println(it2.next()); 
    } 
    } 

Hy vọng điều đó sẽ hữu ích.

+0

Trường hợp "thông thường" bao gồm "có thể nhìn thấy cùng một yếu tố một lần nữa" ... Tôi hơi thất vọng rằng điều này không ném một ngoại lệ, phải trung thực. –

+0

Ngoại lệ không được đảm bảo để được ném, nó là để gỡ lỗi. – sblundy