remove () su List creato da Arrays.asList () genera UnsupportedOperationException


91

Ho una collezione c1<MyClass>e un array a<MyClass>. Sto cercando di convertire l'array in una raccolta c2e lo faccio c1.removeAll(c2), ma questo genera UnsupportedOperationException. Ho scoperto che la asList()classe di Arrays restituisce la Arrays.ArrayListclasse e questa classe eredita la removeAll()dalla AbstractList()cui implementazione viene generata UnsupportedOperationException.

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

C'è un modo per rimuovere gli elementi? per favore aiuto


Risposte:


170

Arrays.asListrestituisce un Listwrapper attorno a un array. Questo wrapper ha una dimensione fissa ed è direttamente supportato dall'array, e come tali le chiamate a setmodificheranno l'array e qualsiasi altro metodo che modifica l'elenco lancerà un UnsupportedOperationException.

Per risolvere questo problema, devi creare un nuovo elenco modificabile copiando il contenuto dell'elenco wrapper. Questo è facile da fare usando il ArrayListcostruttore che accetta Collection:

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

1
Stavo guardando il codice sorgente del java.util.Arrays asList()metodo e sembra che restituisca un file ArrayList. Tuttavia, quando faccio a System.out.println(list.getClass());, ottengo class java.util.Arrays$ArrayList. Quindi usa la ArrayListclasse interna , che non ha un metodo addo remove. Mi chiedo solo qual è il punto di avere una ArrayListclasse interna invece di usare java.util.ArrayListquella e perché non avere un metodo add()e remove()?
Abdul

Correzione al mio commento sopra: ha un metodo adderemove
Abdul

1
@Abdul Perché non esiste una dimensione fissa java.util.ArrayList. Vuoi che un'implementazione di Listciò generi un'eccezione se fai qualcosa di illegale con esso (come l'aggiunta o la rimozione) e ArrayListnon soddisfa quel requisito.
Etienne de Martel

@Abdul Arrays.asListcrea solo un wrapper List. Ma è ancora un java.util.List, quindi deve avere quei metodi. Ma non possono essere applicati perché ciò porterebbe alla creazione di un nuovo array con dimensioni diverse. Cosa che non può essere eseguita perché le modifiche che puoi ancora fare possono essere eseguite sia tramite l'elenco restituito che l'array originale. Ciò non sarà possibile se l'elenco restituito potesse cambiare in modo da eliminare sostanzialmente il riferimento all'array originale.
Adam Hošek

13

Sì, la Arrays.asList(..)raccolta è che non può essere espansa o ridotta (perché è supportata dall'array originale e non può essere ridimensionata).

Se desideri rimuovere elementi, crea new ArrayList(Arrays.asList(..)o rimuovi elementi direttamente dall'array (sarà meno efficiente e più difficile da scrivere)


+1 Questa risposta è l'unica corretta: Arrays.asList () restituisce un elenco non modificabile - questo è ciò che genera l'eccezione. Non ha niente a che fare con l'essere "supportati da un array" ecc ... tutti gli ArrayList sono supportati da array - un grosso problema.
Bohemian

1
Ma se leggessi più a fondo i documenti, ti accorgeresti che non è effettivamente immodificabile ... "Restituisce un elenco di dimensioni fisse supportato dall'array specificato. (Modifiche all'elenco restituito" write through "all'array .) "-1, Etienne ha perfettamente ragione.
Steven Schlansker

1
@Steven Sì, ecco perché dice "dimensione fissa" invece di "non modificabile" o "sola lettura". In realtà, modificherò subito la mia risposta per riflettere questo.
Etienne de Martel

1
@ Bohemian, Le collezioni restituite sono infatti "modificabili" perché è possibile chiamare il metodo "set".
javalearner

2
Se hai intenzione di scegliere lendini in questo modo, potresti anche dire cose insulse come "genera UnsupportedOperationException perché c'è un'istruzione UnsupportedOperationException nel codice". I consumatori di un'API non si preoccupano di quale superclasse di AbstractBlah stia generando un'eccezione, a loro interessa quali sono i contratti e le aspettative della classe che usano. In JVM v + 1, è del tutto possibile che la libreria di classi cambi nel punto in cui viene generata l'eccezione, ma il contratto non cambierà.
Steven Schlansker

7

Questo è il modo in cui Array.asList()funziona, perché è supportato direttamente dall'array. Per ottenere un elenco completamente modificabile, dovresti clonare la raccolta in una raccolta creata da te.

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

1
La lista è modificabile ma solo tramite set (). la raccolta restituita è di dimensioni fisse.
javalearner

Non ho mai detto che fosse immodificabile. Solo che per ottenere un elenco (completamente) modificabile dovresti usare un file ArrayList. La differenza forse non era molto chiara però. :-) Che la lista sia modificabile o meno è una questione di definizione, è "semi-modificabile" ma a mio avviso non completamente modificabile.
Henko
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.