2012-01-11 27 views
11

tôi có mã rất đơn giản:ConcurrentModificationException ném bởi sublist

List<String> list = new ArrayList<String>(); 
    String a = "a"; 
    String b = "b"; 
    String c = "c"; 
    String d = "d"; 

    list.add(a); 
    list.add(b); 
    list.add(c); 

    List<String> backedList = list.subList(0, 2); 
    list.add(0, d); 
    System.out.println("2b: " + backedList); 

Và tôi nhận ConcurrentModificationException ngoại lệ bởi list.add (0, d). Vì vậy, nói chung, đó là vì sublist(). Tôi rất bối rối, bởi vì trong trường hợp sublist() tài liệu nói:

Danh sách quay trở lại được hỗ trợ bởi danh sách này, thay đổi để phi cấu trúc trong danh sách trả về được phản ánh trong danh sách này, và ngược lại.

Bạn có thể giải thích cho tôi nơi bắt giữ không?

+2

Các "bắt" tự giảm dần là thêm một phần tử vào một danh sách là một ** thay đổi cấu trúc **. –

+0

ngược lại trong câu đó là gây hiểu lầm khi bạn đề cập đến @peter, vì như tài liệu (và mã của bạn), giải thích sau, sửa đổi danh sách được sao lưu mà không qua danh sách con sẽ tăng ConcurrentModificationException –

Trả lời

12

subList là chế độ xem đơn giản của danh sách gốc (xem here). Bạn được phép thay đổi các phần tử bên trong nó nhưng không thay đổi cấu trúc của danh sách.

Theo tài liệu, hành vi subList không xác định nếu bạn cố thực hiện thay đổi cấu trúc. Tôi đoán trong việc triển khai cụ thể này, ConcurrentModificationException đã được quyết định là hành vi không xác định.

Ngữ nghĩa của danh sách được trả về bởi phương pháp này trở nên không xác định nếu danh sách sao lưu (tức là danh sách này) được sửa đổi cấu trúc theo bất kỳ cách nào khác ngoài danh sách trả về. (Sửa đổi cấu trúc là những thay đổi kích thước của danh sách này, hoặc nếu không làm phiền nó trong một thời trang như vậy mà lặp lại trong tiến trình có thể mang lại kết quả không chính xác.)

+0

Tôi lãng phí một ngày để kiểm tra xem chính xác đã đi sai, Cảm ơn điều này đã giúp tôi sắp xếp lại các dòng trong mã của tôi –

+0

Xin vui lòng xem câu trả lời tôi được thêm vào dưới đây để làm rõ thêm về bình luận ở trên –

0

list.add (0, d) liên quan đến việc di chuyển tất cả các mục một vị trí và tăng kích thước của danh sách. Đó là thay đổi khá cơ bản.

3

Danh sách trả về được hỗ trợ bởi danh sách này, vì vậy không cấu trúc thay đổi trong danh sách được trả về được phản ánh trong danh sách này và ngược lại. Reference Link

Trên tuyên bố là hoàn toàn chính xác nhưng chúng ta phải ghi nhớ phi cấu trúc thay đổi. Tôi muốn mô tả hai ví dụ minh họa tuyên bố trên. Ví dụ-1: Thực hiện Không cấu trúc thay đổi trong danh sách.

public static void main(String[] args) { 
     List<String> listArr = new ArrayList<>(); 
     listArr.add("Delhi"); 
     listArr.add("Bangalore"); 
     listArr.add("New York"); 
     listArr.add("London"); 

     List<String> listArrSub = listArr.subList(1, 3); 

     System.out.println("List-: " + listArr); 
     System.out.println("Sub List-: " + listArrSub); 

     //Performing Non-Structural Change in list. 
     Collections.swap(listArr, 0, 1); 

     System.out.println("\nAfter Non-Structural Change...\n"); 

     System.out.println("List-: " + listArr); 
     System.out.println("Sub List-: " + listArrSub); 
    } 

Output-:

List-: [Delhi, Bangalore, New York, London] 
Sub List-: [Bangalore, New York] 

After Non-Structural Change... 

List-: [Bangalore, Delhi, New York, London] 
Sub List-: [Delhi, New York] 

Explanation-: Theo tuyên bố tài liệu nói trên của Oracle, hoạt động trao đổi được phản ánh trong cả hai danh sách.

Ví dụ 2: Performing phi cấu thay đổi trong danh sách phụ.

public static void main(String[] args) { 
     List<String> listArr = new ArrayList<>(); 
     listArr.add("Delhi"); 
     listArr.add("Bangalore"); 
     listArr.add("New York"); 
     listArr.add("London"); 

     List<String> listArrSub = listArr.subList(1, 3); 

     System.out.println("List-: " + listArr); 
     System.out.println("Sub List-: " + listArrSub); 

     //Performing Non-Structural Change in sub list. 
     Collections.swap(listArrSub, 0, 1); 

     System.out.println("\nAfter Non-Structural Change...\n"); 

     System.out.println("List-: " + listArr); 
     System.out.println("Sub List-: " + listArrSub); 
    } 

Output-:

List-: [Delhi, Bangalore, New York, London] 
Sub List-: [Bangalore, New York] 

After Non-Structural Change... 

List-: [Delhi, New York, Bangalore, London] 
Sub List-: [New York, Bangalore] 

Explanation-: Theo tuyên bố tài liệu nói trên của Oracle, hoạt động trao đổi được phản ánh trong cả hai danh sách tuy nhiên nó đã được thực hiện trên danh sách phụ.

Như chúng ta đã thấy Không cấu trúc thay đổi trong hai ví dụ nói trên. Bây giờ chúng ta hãy xem Kết cấu thay đổi theo tuyên bố dưới đây được đưa ra trong tài liệu của Oracle.

Ngữ nghĩa của danh sách được trả về bởi phương pháp này trở nên không xác định nếu danh sách sao lưu (tức là danh sách này) được sửa đổi cấu trúc theo bất kỳ cách nào khác ngoài danh sách trả về. (Sửa đổi cấu là những thay đổi kích thước của danh sách này, hoặc nếu không làm xáo trộn nó trong một thời trang như vậy lặp đi lặp lại trong tiến trình có thể mang lại kết quả không chính xác.)

Ví dụ 3: Performing cấu thay đổi trong danh sách .

public static void main(String[] args) { 
     List<String> listArr = new ArrayList<>(); 
     listArr.add("Delhi"); 
     listArr.add("Bangalore"); 
     listArr.add("New York"); 
     listArr.add("London"); 

     List<String> listArrSub = listArr.subList(1, 3); 

     System.out.println("List-: " + listArr); 
     System.out.println("Sub List-: " + listArrSub); 

     //Performing Structural Change in list. 
     listArr.add("Mumbai"); 

     System.out.println("\nAfter Structural Change...\n"); 

     System.out.println("List-: " + listArr); 
     System.out.println("Sub List-: " + listArrSub); 
    } 

Output-:

List-: [Delhi, Bangalore, New York, London] 
Sub List-: [Bangalore, New York] 

After Structural Change... 

List-: [Delhi, Bangalore, New York, London, Mumbai] 
Exception in thread "main" java.util.ConcurrentModificationException 
    at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1231) 
    at java.util.ArrayList$SubList.listIterator(ArrayList.java:1091) 
    at java.util.AbstractList.listIterator(AbstractList.java:299) 
    at java.util.ArrayList$SubList.iterator(ArrayList.java:1087) 
    at java.util.AbstractCollection.toString(AbstractCollection.java:454) 
    at java.lang.String.valueOf(String.java:2982) 
    at java.lang.StringBuilder.append(StringBuilder.java:131) 
    at infosys.Research.main(Research.java:26) 

Explanation-: Theo tuyên bố tài liệu nói trên của Oracle, vận hành sửa đổi cấu trúc được ném java.util.ConcurrentModificationException ngoại lệ bất cứ khi nào Ngữ nghĩa của danh sách được trả về bởi phương pháp này trở thành không xác định nếu sự ủng hộ danh sách (ví dụ, danh sách này) được cấu trúc sửa đổi trong bất kỳ cách nào khác hơn thông qua danh sách trả về.

Ví dụ-4: Performing cấu sự thay đổi trong sub danh sách.

public static void main(String[] args) { 
     List<String> listArr = new ArrayList<>(); 
     listArr.add("Delhi"); 
     listArr.add("Bangalore"); 
     listArr.add("New York"); 
     listArr.add("London"); 

     List<String> listArrSub = listArr.subList(1, 3); 

     System.out.println("List-: " + listArr); 
     System.out.println("Sub List-: " + listArrSub); 

     //Performing Structural Change in sub list. 
     listArrSub.add("Mumbai"); 

     System.out.println("\nAfter Structural Change...\n"); 

     System.out.println("List-: " + listArr); 
     System.out.println("Sub List-: " + listArrSub); 
    } 

Output-:

List-: [Delhi, Bangalore, New York, London] 
Sub List-: [Bangalore, New York] 

After Structural Change... 

List-: [Delhi, Bangalore, New York, Mumbai, London] 
Sub List-: [Bangalore, New York, Mumbai] 

Explanation-: cấu sửa đổi vào danh sách quay trở lại được làm việc tốt và phản ánh trong danh sách hoàn toàn.

0

Kịch bản trong đó lỗi này đã gặp phải

  • Tôi đã có một danh sách (danh sách ban đầu) với giả sử 100 mục
  • Sắp xếp danh sách ban đầu trong thứ tự tăng dần
  • sublist nó -> tạo sublist (danh sách phụ được đặt hàng tăng dần)
  • Sắp xếp danh sách gốc theo thứ tự giảm dần
  • Lặp lại danh sách phụ (danh sách phụ theo thứ tự tăng dần) liệt kê

đồng thời sửa đổi Got ngoại lệ

Fix để trên kịch bản

  • Tôi đã có một danh sách (danh sách ban đầu) với giả sử 100 mục
  • Sắp xếp nó theo thứ tự tăng dần
  • Danh sách phụ -> danh sách phụ được tạo (danh sách phụ được đặt hàng tăng dần)
  • lặp trên sublisted (tăng dần ra lệnh sublist) danh sách
  • Sắp xếp danh sách theo thứ tự ban đầu
Các vấn đề liên quan