remove () зі списку, створеного Arrays.asList (), викидає UnsupportedOperationException


91

У мене є колекція c1<MyClass>та масив a<MyClass>. Я намагаюся перетворити масив на колекцію c2і робити c1.removeAll(c2), але це кидає UnsupportedOperationException. Я виявив, що asList()клас Arrays повертає Arrays.ArrayListклас, і цей клас успадковує те, removeAll()від AbstractList()реалізації якого викидає UnsupportedOperationException.

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

Чи є спосіб видалити елементи? будь ласка, допоможіть


відповідне запитання: stackoverflow.com/questions/2965747/…
Рам,

Відповіді:


170

Arrays.asListповертає Listобгортку навколо масиву. Ця обгортка має фіксований розмір і безпосередньо підкріплюється масивом, і тому такі виклики setмодифікують масив, а будь-який інший метод, що змінює список, видасть UnsupportedOperationException.

Щоб виправити це, вам потрібно створити новий модифікований список, скопіювавши вміст списку обгортки. Це легко зробити, використовуючи ArrayListконструктор, який приймає Collection:

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

1
Я дивився на вихідний код java.util.Arrays asList()методу, і він, здається, повертає файл ArrayList. Однак, коли я це роблю System.out.println(list.getClass());, я отримую class java.util.Arrays$ArrayList. Отже, він використовує внутрішній ArrayListклас, який не має addані removeметоду. Мені просто цікаво, який сенс мати внутрішній ArrayListклас, а не використовувати його, java.util.ArrayListі чому б не мати метод add()and remove()?
Абдул

Виправлення мого вищезазначеного коментаря: у нього є метод addі removeметод
Абдул

1
@Abdul Оскільки не існує такого поняття, як фіксований розмір java.util.ArrayList. Вам потрібна реалізація, Listяка видає виняток, якщо ви робите з нею щось незаконне (наприклад, додавання або видалення), і ArrayListне задовольняє цій вимозі.
Етьєн де Мартель

@Abdul Arrays.asListпросто створює обгортку List. Але це все-таки java.util.List, тому вони повинні мати ці методи. Але їх не можна застосувати, оскільки це призведе до створення нового масиву з різним розміром. Що неможливо зробити, оскільки модифікації, які ви все ще можете зробити, можна здійснити як через повернутий список, так і через оригінальний масив. Це буде неможливо, якщо повернутий Список міг би змінитися таким чином, що в основному він викинув би оригінальне посилання на масив.
Адам Гошек

13

Так, Arrays.asList(..)це колекція, яку неможливо розширити або зменшити (оскільки вона підтримується вихідним масивом і не може змінювати розмір).

Якщо ви хочете видалити елементи, або створіть a, new ArrayList(Arrays.asList(..)або видаліть елементи безпосередньо з масиву (це буде менш ефективно і складніше писати)


+1 Ця відповідь є єдино правильною: Arrays.asList () повертає немодифікований список - ось що викликає виняток. Це нічого спільного з "підтримкою масиву" тощо ... всі ArrayLists підтримуються масивами - велика справа.
Чеська

1
Але якщо ви прочитаєте далі документи, ви зрозумієте, що насправді це не можна модифікувати ... "Повертає список фіксованого розміру, підкріплений вказаним масивом. (Зміни у поверненому списку" записувати "до масиву .) "-1, Етьєн цілком правий.
Steven Schlansker

1
@Steven Так, тому в ньому написано "фіксований розмір", а не "немодифікується" або "лише для читання". Власне, я зараз відредагую свою відповідь, щоб це відобразити.
Етьєн де Мартель,

1
@Bohemian, Повернуті колекції неможливо змінити, оскільки можна викликати метод 'set'.
javalearner

2
Якщо ви збираєтеся вибирати такі гніди, ви можете також сказати такі безглузді речі, як "він кидає UnsupportedOperationException, оскільки в коді є оператор throw UnsupportedOperationException". Споживачам API байдуже, який суперклас AbstractBlah видає виняток, їм цікаво, якими є контракти та очікування класу, яким вони користуються. У JVM v + 1 цілком можливо, що бібліотека класів змінюється там, де виникає виняток - але контракт не зміниться.
Steven Schlansker

7

Так Array.asList()працює, оскільки він безпосередньо підкріплений масивом. Щоб отримати повністю модифікований список, вам доведеться клонувати колекцію в колекцію, створену власноруч.

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

1
Список можна змінювати, але лише через set (). повернута колекція має фіксований розмір.
javalearner

Я ніколи насправді не говорив, що це неможливо змінити. Тільки для того, щоб отримати (повністю) модифікуваний список, вам довелося б використовувати ArrayList. Хоча різниця, можливо, не була надто чіткою. :-) Чи можна змінювати список чи ні - це питання визначення, він "напів модифікується", але, на мій погляд, не повністю модифікується.
henko
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.