remove () na liście utworzonej przez Arrays.asList () zgłasza wyjątek UnsupportedOperationException


91

Mam kolekcję c1<MyClass>i tablicę a<MyClass>. Próbuję przekonwertować tablicę na kolekcję c2i zrobić c1.removeAll(c2), ale to wyrzuca UnsupportedOperationException. Okazało się, że asList()tablice klasy zwrotów Arrays.ArrayListklasy i tej klasie dziedziczy removeAll()z AbstractList()którego realizacja rzuca UnsupportedOperationException.

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

Czy jest jakiś sposób na usunięcie elementów? proszę pomóż


Odpowiedzi:


173

Arrays.asListzwraca Listopakowanie wokół tablicy. Ta otoka ma stały rozmiar i jest bezpośrednio obsługiwana przez tablicę, a zatem wywołania funkcji setzmodyfikują tablicę, a każda inna metoda modyfikująca listę wyrzuci UnsupportedOperationException.

Aby to naprawić, musisz utworzyć nową modyfikowalną listę, kopiując zawartość listy opakowań. Można to łatwo zrobić za pomocą ArrayListkonstruktora, który przyjmuje Collection:

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

1
Patrzyłem na kod źródłowy java.util.Arrays asList()metody i wydaje się, że zwraca plik ArrayList. Jednak kiedy to zrobię System.out.println(list.getClass());, dostaję class java.util.Arrays$ArrayList. Dlatego używa ArrayListklasy wewnętrznej , która nie ma metody addani remove. Zastanawiam się tylko, jaki jest sens posiadania ArrayListklasy wewnętrznej zamiast używania java.util.ArrayListjednej i dlaczego nie mieć metody add()and remove()?
Abdul

Korekta mojego powyższego komentarza: ma metodę addiremove
Abdul

1
@Abdul Ponieważ nie ma czegoś takiego jak ustalony rozmiar java.util.ArrayList. Chcesz, aby implementacja Listzgłaszała wyjątek, jeśli zrobisz z nią coś nielegalnego (na przykład dodawanie lub usuwanie) i ArrayListnie spełnia tego wymagania.
Etienne de Martel

@Abdul Arrays.asListpo prostu tworzy opakowanie List. Ale nadal jest java.util.List, więc musi mieć te metody. Nie można ich jednak zastosować, ponieważ doprowadziłoby to do utworzenia nowej tablicy o innym rozmiarze. Nie można tego zrobić, ponieważ modyfikacje, które nadal możesz wykonać, można wykonać zarówno za pomocą zwróconej listy, jak i oryginalnej tablicy. Nie będzie to możliwe, jeśli zwrócona lista może się zmienić tak, że w zasadzie wyrzuci oryginalne odwołanie do tablicy.
Adam Hošek

13

Tak, Arrays.asList(..)kolekcja jest, której nie można rozwinąć ani zmniejszyć (ponieważ jest obsługiwana przez oryginalną tablicę i nie można jej zmienić).

Jeśli chcesz usunąć elementy, utwórz element new ArrayList(Arrays.asList(..)lub usuń elementy bezpośrednio z tablicy (będzie to mniej wydajne i trudniejsze do napisania)


+1 Ta odpowiedź jest jedyna poprawna: Arrays.asList () zwraca niemodyfikowalną listę - to właśnie zgłasza wyjątek. Nie ma to nic wspólnego z byciem "wspieranym przez tablicę" itp ... wszystkie ArrayLists są obsługiwane przez tablice - wielka sprawa.
Bohemian

1
Ale jeśli zagłębisz się w dokumentację, zdasz sobie sprawę, że w rzeczywistości nie jest ona niemodyfikowalna ... "Zwraca listę o stałym rozmiarze, popartą określoną tablicą. (Zmiana zwracanej listy" zapisywanie "do tablicy .) „-1, Etienne ma rację.
Steven Schlansker

1
@Steven Tak, dlatego jest napisane „stały rozmiar” zamiast „niemodyfikowalne” lub „tylko do odczytu”. Właściwie to teraz edytuję moją odpowiedź, aby to odzwierciedlić.
Etienne de Martel

1
@Bohemian, Zwracane kolekcje są w rzeczywistości „modyfikowalne”, ponieważ można wywołać metodę „set”.
javalearner

2
Jeśli masz zamiar wybierać takie gnidy, równie dobrze możesz powiedzieć niewyraźne rzeczy, takie jak „rzuca UnsupportedOperationException, ponieważ w kodzie znajduje się instrukcja wyrzucenia UnsupportedOperationException”. Konsumentów API nie obchodzi, która superklasa AbstractBlah rzuca wyjątek, obchodzi ich, jakie są kontrakty i oczekiwania klasy, której używają. W JVM v + 1 jest całkowicie możliwe, że biblioteka klas zmienia się, gdy zgłaszany jest wyjątek - ale umowa nie ulegnie zmianie.
Steven Schlansker

7

W ten sposób Array.asList()działa, ponieważ jest bezpośrednio obsługiwany przez tablicę. Aby uzyskać w pełni modyfikowalną listę, musiałbyś sklonować kolekcję do kolekcji utworzonej przez siebie.

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

1
Listę można modyfikować, ale tylko za pomocą metody set (). zwracana kolekcja ma stały rozmiar.
javalearner

Właściwie nigdy nie powiedziałem, że jest niemodyfikowalny. Wystarczy, że aby uzyskać (w pełni) modyfikowalną listę, musisz użyć pliku ArrayList. Być może różnica nie była jednak zbyt wyraźna. :-) To, czy lista jest modyfikowalna, czy nie, jest kwestią definicji, jest „częściowo modyfikowalna”, ale moim zdaniem nie jest w pełni modyfikowalna.
henko,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.