remove () in der von Arrays.asList () erstellten Liste löst eine UnsupportedOperationException aus

91

Ich habe eine Sammlung c1<MyClass>und ein Array a<MyClass>. Ich versuche, das Array in eine Sammlung zu konvertieren c2und zu tun c1.removeAll(c2), aber das wirft UnsupportedOperationException. Ich fand heraus, dass die asList()of Arrays-Klasse eine Klasse zurückgibt Arrays.ArrayListund diese Klasse die Klasse erbt, removeAll()von AbstractList()deren Implementierung ausgelöst wird UnsupportedOperationException.

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

Gibt es eine Möglichkeit, die Elemente zu entfernen? Bitte helfen Sie

Javalearner
quelle

Antworten:

170

Arrays.asListGibt einen ListWrapper um ein Array zurück. Dieser Wrapper hat eine feste Größe und wird direkt vom Array unterstützt. Durch Aufrufe von setwird das Array geändert, und jede andere Methode, die die Liste ändert, löst eine aus UnsupportedOperationException.

Um dies zu beheben, müssen Sie eine neue änderbare Liste erstellen, indem Sie den Inhalt der Wrapper-Liste kopieren. Dies ist einfach, indem Sie den ArrayListKonstruktor verwenden, der Folgendes verwendet Collection:

Collection c = new ArrayList(Arrays.asList(la));
Etienne de Martel
quelle
1
Ich habe mir den Quellcode für die java.util.Arrays asList()Methode angesehen und er scheint eine zurückzugeben ArrayList. Wenn ich jedoch eine mache System.out.println(list.getClass());, bekomme ich class java.util.Arrays$ArrayList. Es wird also die innere ArrayListKlasse verwendet, die keine addoder- removeMethode hat. Ich frage mich nur, was es bringt, eine innere ArrayListKlasse zu haben, anstatt die java.util.ArrayListeine zu verwenden, und warum nicht eine add()und- remove()Methode?
Abdul
Korrektur zu meinem obigen Kommentar: Es hat eine addund removeMethode
Abdul
1
@Abdul Weil es keine feste Größe gibt java.util.ArrayList. Sie möchten, dass eine Implementierung Listeine Ausnahme auslöst, wenn Sie damit etwas Illegales tun (z. B. Hinzufügen oder Entfernen), und ArrayListdiese Anforderung nicht erfüllt.
Etienne de Martel
@Abdul Arrays.asListerstellt nur einen Wrapper List. Aber es ist immer noch eine java.util.List, also muss es diese Methoden haben. Sie können jedoch nicht angewendet werden, da dies zur Erstellung eines neuen Arrays mit unterschiedlicher Größe führen würde. Dies ist nicht möglich, da die Änderungen, die Sie noch vornehmen können, sowohl über die zurückgegebene Liste als auch über das ursprüngliche Array vorgenommen werden können. Dies ist nicht möglich, wenn sich die zurückgegebene Liste so ändern könnte, dass die ursprüngliche Array-Referenz im Grunde genommen weggeworfen wird.
Adam Hošek
13

Ja, die Arrays.asList(..)is-Sammlung kann nicht erweitert oder verkleinert werden (da sie vom ursprünglichen Array unterstützt wird und die Größe nicht geändert werden kann).

Wenn Sie Elemente entfernen möchten, erstellen Sie entweder ein new ArrayList(Arrays.asList(..)Element oder entfernen Sie es direkt aus dem Array (dies ist weniger effizient und schwieriger zu schreiben).

Bozho
quelle
+1 Diese Antwort ist die einzig richtige: Arrays.asList () gibt eine nicht veränderbare Liste zurück - das ist es, was die Ausnahme auslöst . Es hat nichts damit zu tun, "von einem Array unterstützt" zu werden usw. Alle ArrayLists werden von Arrays unterstützt - eine große Sache.
Bohemian
1
Wenn Sie jedoch weiter in die Dokumente hineinlesen, werden Sie feststellen, dass sie nicht unveränderbar sind ... "Gibt eine Liste mit fester Größe zurück, die vom angegebenen Array unterstützt wird. (Änderungen an der zurückgegebenen Liste werden in das Array" durchgeschrieben " .) "-1, Etienne hat ganz recht.
Steven Schlansker
1
@Steven Ja, deshalb steht dort "feste Größe" statt "nicht modifizierbar" oder "schreibgeschützt". Eigentlich werde ich meine Antwort jetzt bearbeiten, um das zu reflektieren.
Etienne de Martel
1
@Bohemian, Die zurückgegebenen Sammlungen sind tatsächlich 'änderbar', da die Methode 'set' aufgerufen werden kann.
Javalearner
2
Wenn Sie solche Nissen auswählen, können Sie auch vage Dinge sagen wie "es löst UnsupportedOperationException aus, weil der Code eine UnsupportedOperationException-Anweisung enthält". Den Verbrauchern einer API ist es egal, welche AbstractBlah-Superklasse eine Ausnahme auslöst. Sie kümmern sich darum, welche Verträge und Erwartungen die von ihnen verwendete Klasse hat. In JVM v + 1 ist es durchaus möglich, dass sich die Klassenbibliothek dort ändert, wo die Ausnahme ausgelöst wird - der Vertrag ändert sich jedoch nicht.
Steven Schlansker
7

Das Array.asList()funktioniert so, weil es direkt vom Array unterstützt wird. Um eine vollständig änderbare Liste zu erhalten, müssten Sie die Sammlung in eine von Ihnen selbst erstellte Sammlung klonen.

Collection c = new ArrayList(Arrays.asList(la))
henko
quelle
1
Die Liste kann geändert werden, jedoch nur über set (). Die zurückgegebene Sammlung hat eine feste Größe.
Javalearner
Ich habe nie gesagt, dass es nicht veränderbar ist. Nur um eine (vollständig) modifizierbare Liste zu erhalten, müssten Sie eine verwenden ArrayList. Der Unterschied war vielleicht nicht allzu klar. :-) Ob die Liste modifizierbar ist oder nicht, ist eine Frage der Definition, sie ist "semi-modifizierbar", aber meiner Ansicht nach nicht vollständig modifizierbar.
Henko