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.