566 votes

Pourquoi je reçois UnsupportedOperationException lorsque vous essayez de supprimer de la liste ?

J’ai ce code :

J’obtiens ceci :

Comment serait-ce la bonne façon ? Java.15

1150voto

polygenelubricants Points 136838

Pas mal de problèmes avec votre code:

Sur Arrays.asList retour d'une taille fixe la liste

À partir de l'API:

Arrays.asList: Retourne une taille fixe la liste soutenue par le tableau spécifié.

Vous ne pouvez pas add ; vous ne pouvez pas remove . Vous ne pouvez pas modifier structurellement l' List.

Fix

Créer un LinkedList, qui prend en charge plus rapide remove.

List<String> list = new LinkedList<String>(Arrays.asList(split));

Sur split prise de regex

À partir de l'API:

String.split(String regex): Divise cette chaîne autour de matchs de l' expression régulière.

| est une regex caractère de remplacement; si vous voulez diviser sur un littéral |, vous devez échapper à l' \|, qui comme Java littéral de chaîne est "\\|".

Correctif:

template.split("\\|")

Sur meilleur algorithme

Au lieu d'appeler remove un à un au hasard des indices, il est préférable de générer suffisamment de nombres aléatoires dans la gamme, puis traversée de la List une fois avec un listIterator(), appelant remove() à des indices appropriés. Il y a des questions sur stackoverflow sur la façon de générer de l'aléatoire, mais distincts des nombres dans une plage donnée.

Avec cela, votre algorithme serait O(N).

167voto

Nick Orton Points 947

Celui-ci m’a brûlé plusieurs fois. ``crée une liste non modifiable. De la Javadoc : renvoie une liste de taille fixe , soutenue par le tableau spécifié.

Créez une nouvelle liste avec le même contenu :

Cela créera une petite poubelle supplémentaire, mais vous serez en mesure de muter il.

68voto

Roman Points 21807

Probablement parce que vous travaillez avec une enveloppe non modifiable.

Changez cette ligne :

Cette ligne :

6voto

Andreas_D Points 64111

Il suffit de lire la JavaDoc de la asList méthode:

Retourne un {@code Liste} des objets dans le tableau spécifié. La taille de le {@code Liste} ne peut pas être modifié, c'est à dire l'ajout et la suppression sont non pris en charge, mais les éléments peuvent être ensemble. La fixation d'un élément modifie l' sous-jacent tableau.

C'est à partir de la version 6 de Java, mais il semble que c'est la même chose pour android java.

MODIFIER

Le type de la liste résultante est - Arrays.ArrayList, ce qui est une classe privée à l'intérieur de Arrays.class. Pratiquement parlant, il n'en est rien, mais une Liste d'œil sur le tableau que vous avez passé avec Arrays.asList. Avec une conséquence: si vous modifiez le tableau, la liste est aussi changé. Et parce qu'un tableau n'est pas redimensionnables, supprimer et ajouter de l'opération doit être pris en charge.

4voto

Dimitris Andreou Points 5398

Les tableaux de.asList() renvoie une liste qui n'autorise pas les opérations affectant sa taille (notez que ce n'est pas la même chose que "inmodifiable").

Vous pourriez faire new ArrayList<String>(Arrays.asList(split)); pour créer une copie réelle, mais en voyant ce que vous essayez de faire, voici une suggestion supplémentaire (vous avez un O(n^2) algorithme ci-dessous à droite).

Vous souhaitez supprimer list.size() - count (appelons cette k) aléatoire des éléments de la liste. Il suffit de choisir au hasard autant d'éléments et de les échanger à la fin de l' k des postes de la liste, puis supprimer l'ensemble de la gamme (par exemple à l'aide de sous-liste() et clear ()). Qui serait à son tour à un lean and mean O(n) algorithme (O(k) est plus précis).

Mise à jour: Comme mentionné ci-dessous, cet algorithme n'a de sens que si les éléments sont non ordonnée, par exemple, si la Liste représente un Sac. Si, d'autre part, la Liste a un ordre significatif, cet algorithme ne seraient pas préserver (polygenelubricants' algorithme au lieu de cela).

Mise à jour 2: Donc, rétrospectivement, une meilleure (linéaire, le maintien de l'ordre, mais avec O(n) de nombres aléatoires) algorithme serait quelque chose comme ceci:

LinkedList<String> elements = ...; //to avoid the slow ArrayList.remove()
int k = elements.size() - count; //elements to select/delete
int remaining = elements.size(); //elements remaining to be iterated
for (Iterator i = elements.iterator(); k > 0 && i.hasNext(); remaining--) {
  i.next();
  if (random.nextInt(remaining) < k) {
     //or (random.nextDouble() < (double)k/remaining)
     i.remove();
     k--;
  }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X