remove () sur la liste créée par Arrays.asList () lève une exception UnsupportedOperationException

91

J'ai une collection c1<MyClass>et un tableau a<MyClass>. J'essaye de convertir le tableau en collection c2et fais c1.removeAll(c2), mais cela jette UnsupportedOperationException. J'ai trouvé que le asList()des rendements de classe Arrays Arrays.ArrayListclasse et la cette classe hérite removeAll()de AbstractList()dont la mise en œuvre jette UnsupportedOperationException.

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

Existe-t-il un moyen de supprimer les éléments? s'il vous plaît aider

javalearner
la source

Réponses:

170

Arrays.asListrenvoie un Listwrapper autour d'un tableau. Ce wrapper a une taille fixe et est directement sauvegardé par le tableau, et en tant que tel, les appels à setmodifieront le tableau, et toute autre méthode qui modifie la liste lèvera un UnsupportedOperationException.

Pour résoudre ce problème, vous devez créer une nouvelle liste modifiable en copiant le contenu de la liste wrapper. C'est facile à faire en utilisant le ArrayListconstructeur qui prend un Collection:

Collection c = new ArrayList(Arrays.asList(la));
Etienne de Martel
la source
1
Je regardais le code source de la java.util.Arrays asList()méthode, et il semble renvoyer un fichier ArrayList. Cependant, quand je fais un System.out.println(list.getClass());, je reçois class java.util.Arrays$ArrayList. Il utilise donc la ArrayListclasse interne , qui n'a pas de méthode addou remove. Je me demande simplement quel est l'intérêt d'avoir une ArrayListclasse interne au lieu d'utiliser celle- java.util.ArrayListci et pourquoi pas une méthode add()and remove()?
Abdul
Correction à mon commentaire ci-dessus: il a une méthode addetremove
Abdul
1
@Abdul Parce qu'il n'y a pas de taille fixe java.util.ArrayList. Vous voulez qu'une implémentation de Listcela lève une exception si vous faites quelque chose d'illégal avec elle (comme l'ajout ou la suppression), et ArrayListne répond pas à cette exigence.
Etienne de Martel
@Abdul Arrays.asListcrée simplement un wrapper List. Mais c'est toujours un java.util.List, donc il doit avoir ces méthodes. Mais ils ne peuvent pas être appliqués car cela conduirait à créer un nouveau tableau de taille différente. Ce qui ne peut pas être fait car les modifications que vous pouvez encore effectuer peuvent être effectuées à la fois via la liste renvoyée et le tableau d'origine. Cela ne sera pas possible si la liste renvoyée pouvait changer de manière à éliminer la référence de tableau d'origine.
Adam Hošek
13

Oui, la Arrays.asList(..)collection est qui ne peut pas être étendue ou réduite (car elle est sauvegardée par le tableau d'origine et ne peut pas être redimensionnée).

Si vous souhaitez supprimer des éléments, créez un new ArrayList(Arrays.asList(..)ou supprimez des éléments directement du tableau (ce sera moins efficace et plus difficile à écrire)

Bozho
la source
+1 Cette réponse est la seule correcte: Arrays.asList () renvoie une liste non modifiable - c'est ce qui lève l'exception. Cela n'a rien à voir avec le fait d'être "sauvegardé par un tableau" etc ... toutes les ArrayLists sont soutenues par des tableaux - ce qui est un gros problème.
Bohème
1
Mais si vous lisez plus loin dans la documentation, vous vous rendrez compte que ce n'est pas réellement non modifiable ... "Renvoie une liste de taille fixe soutenue par le tableau spécifié. .) "-1, Etienne a tout à fait raison.
Steven Schlansker
1
@Steven Oui, c'est pourquoi il dit "taille fixe" plutôt que "non modifiable" ou "lecture seule". En fait, je vais modifier ma réponse maintenant pour refléter cela.
Etienne de Martel
1
@Bohemian, Les collections renvoyées sont en fait 'modifiables' car il est possible d'appeler la méthode 'set'.
javalearner
2
Si vous allez choisir des lentes comme ça, vous pourriez aussi bien dire des choses insipides comme "il lance une exception UnsupportedOperationException parce qu'il y a une instruction throw UnsupportedOperationException dans le code". Les consommateurs d'une API ne se soucient pas de la superclasse de AbstractBlah qui lève une exception, ils se soucient des contrats et des attentes de la classe qu'ils utilisent. Dans JVM v + 1, il est tout à fait possible que la bibliothèque de classes change là où l'exception est levée - mais le contrat ne changera pas.
Steven Schlansker
7

C'est ainsi que cela Array.asList()fonctionne, car il est directement soutenu par la baie. Pour obtenir une liste entièrement modifiable, vous devez cloner la collection dans une collection créée par vous-même.

Collection c = new ArrayList(Arrays.asList(la))
Henko
la source
1
La liste est modifiable mais uniquement via set (). la collection retournée est de taille fixe.
javalearner
Je n'ai jamais dit que c'était non modifiable. Juste que pour obtenir une liste (entièrement) modifiable, vous devrez utiliser un fichier ArrayList. La différence n'était peut-être pas trop claire cependant. :-) Que la liste soit modifiable ou non est une question de définition, elle est "semi-modifiable" mais pas totalement modifiable à mon avis.
henko