remove () trên Danh sách được tạo bởi Arrays.asList () ném UnsupportedOperationException


91

Tôi có một bộ sưu tập c1<MyClass>và một mảng a<MyClass>. Tôi đang cố gắng chuyển đổi mảng thành một bộ sưu tập c2và thực hiện c1.removeAll(c2), Nhưng điều này ném UnsupportedOperationException. Tôi phát hiện ra rằng asList()các Mảng lợi nhuận lớp Arrays.ArrayListlớp và các lớp này được thừa hưởng những removeAll()từ AbstractList()mà thực hiện ném UnsupportedOperationException.

    Myclass la[] = getMyClass();
    Collection c = Arrays.asList(la);
    c.removeAll(thisAllreadyExistingMyClass);

Có cách nào để loại bỏ các phần tử? xin vui lòng giúp đỡ


Câu trả lời:


170

Arrays.asListtrả về một Listtrình bao bọc xung quanh một mảng. Trình bao bọc này có kích thước cố định và được hỗ trợ trực tiếp bởi mảng và như vậy các lệnh gọi tới setsẽ sửa đổi mảng và bất kỳ phương thức nào khác sửa đổi danh sách sẽ ném ra một UnsupportedOperationException.

Để khắc phục điều này, bạn phải tạo một danh sách có thể sửa đổi mới bằng cách sao chép nội dung của danh sách trình bao bọc. Điều này rất dễ thực hiện bằng cách sử dụng hàm ArrayListtạo có Collection:

Collection c = new ArrayList(Arrays.asList(la));

1
Tôi đã xem mã nguồn cho java.util.Arrays asList()phương thức và có vẻ như nó trả về một ArrayList. Tuy nhiên, khi tôi làm một System.out.println(list.getClass());, tôi nhận được class java.util.Arrays$ArrayList. Vì vậy, nó sử dụng ArrayListlớp bên trong , lớp không có addhoặc removephương thức. Tôi chỉ tự hỏi lợi ích của việc có một ArrayListlớp bên trong thay vì sử dụng java.util.ArrayListmột lớp và tại sao không có một add()remove()phương thức?
Abdul

Correction để bình luận trên của tôi: nó có một addremovephương pháp
Abdul

1
@Abdul Vì không có thứ gọi là kích thước cố định java.util.ArrayList. Bạn muốn triển khai Listđiều đó ném ra một ngoại lệ nếu bạn làm điều gì đó bất hợp pháp với nó (chẳng hạn như thêm hoặc xóa) và ArrayListkhông đáp ứng yêu cầu đó.
Etienne de Martel

@Abdul Arrays.asListchỉ tạo một trình bao bọc List. Nhưng nó vẫn là một java.util.List, vì vậy nó phải có những phương pháp đó. Nhưng chúng không thể được áp dụng vì điều đó sẽ dẫn đến việc tạo ra một mảng mới với kích thước khác nhau. Điều này không thể được thực hiện vì các sửa đổi bạn vẫn có thể thực hiện có thể được thực hiện cả thông qua Danh sách trả về và mảng ban đầu. Điều này sẽ không thể xảy ra nếu Danh sách trả về có thể thay đổi để về cơ bản nó sẽ loại bỏ tham chiếu mảng ban đầu.
Adam Hošek

13

Đúng vậy, Arrays.asList(..)tập hợp là không thể mở rộng hoặc thu nhỏ (vì nó được hỗ trợ bởi mảng ban đầu và không thể thay đổi kích thước).

Nếu bạn muốn xóa các phần tử, hãy tạo một new ArrayList(Arrays.asList(..)hoặc xóa các phần tử trực tiếp khỏi mảng (điều đó sẽ kém hiệu quả hơn và khó viết hơn)


+1 Câu trả lời này là câu đúng duy nhất: Arrays.asList () trả về một danh sách không thể thay đổi - đó là những gì đang tạo ra ngoại lệ. Nó không liên quan gì đến việc được "hỗ trợ bởi một mảng", v.v ... tất cả các ArrayLists đều được hỗ trợ bởi mảng - vấn đề lớn.
Bohemian

1
Nhưng nếu bạn đọc thêm tài liệu, bạn sẽ nhận ra rằng nó không thực sự là không thể sửa đổi ... "Trả về danh sách có kích thước cố định được hỗ trợ bởi mảng đã chỉ định. (Các thay đổi đối với danh sách được trả về" ghi qua "vào mảng .) "-1, Etienne khá đúng.
Steven Schlansker

1
@Steven Có, đó là lý do tại sao nó nói "kích thước cố định" thay vì "không thể sửa đổi" hoặc "chỉ đọc". Trên thực tế, tôi sẽ chỉnh sửa câu trả lời của mình ngay bây giờ để phản ánh điều đó.
Etienne de Martel

1
@Bohemian, Các bộ sưu tập trả về là không chính xác 'có thể sửa đổi' vì có thể gọi phương thức 'set'.
javalearner

2
Nếu bạn định chọn nits như vậy, bạn cũng có thể nói những điều khó hiểu như "nó ném UnsupportedOperationException vì có một câu lệnh ném UnsupportedOperationException trong mã". Người tiêu dùng API không quan tâm lớp siêu AbstractBlah nào đưa ra ngoại lệ, họ quan tâm các hợp đồng và kỳ vọng của lớp họ sử dụng là gì. Trong JVM v + 1, hoàn toàn có thể thư viện lớp thay đổi nơi ngoại lệ được ném - nhưng hợp đồng sẽ không thay đổi.
Steven Schlansker

7

Đó là cách Array.asList()hoạt động, bởi vì nó được hỗ trợ trực tiếp bởi mảng. Để có được danh sách đầy đủ có thể sửa đổi, bạn sẽ phải sao chép bộ sưu tập thành bộ sưu tập do chính bạn tạo.

Collection c = new ArrayList(Arrays.asList(la))

1
Danh sách có thể sửa đổi nhưng chỉ thông qua set (). bộ sưu tập được trả lại có kích thước cố định.
javalearner

Tôi chưa bao giờ thực sự nói rằng nó không thể thay đổi được. Chỉ vậy để có được một danh sách (đầy đủ) có thể sửa đổi, bạn sẽ phải sử dụng một ArrayList. Sự khác biệt có lẽ không quá rõ ràng. :-) Danh sách có thể sửa đổi được hay không là một câu hỏi về định nghĩa, nó là "bán sửa đổi" nhưng không hoàn toàn có thể sửa đổi theo quan điểm của tôi.
henko
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.