J'ai ce code:
public static String SelectRandomFromTemplate(String template,int count) {
String[] split = template.split("|");
List<String> list=Arrays.asList(split);
Random r = new Random();
while( list.size() > count ) {
list.remove(r.nextInt(list.size()));
}
return StringUtils.join(list, ", ");
}
J'ai compris:
06-03 15:05:29.614: ERROR/AndroidRuntime(7737): Java.lang.UnsupportedOperationException
06-03 15:05:29.614: ERROR/AndroidRuntime(7737): at Java.util.AbstractList.remove(AbstractList.Java:645)
Comment serait-ce la bonne façon? Java.15
Quelques problèmes avec votre code:
Arrays.asList
_ renvoyant une liste de taille fixeDe l'API:
Arrays.asList
: Retourne une liste de taille fixe sauvegardée par le tableau spécifié.
Vous ne pouvez pas add
à cela; vous ne pouvez pas remove
partir de là. Vous ne pouvez pas modifier structurellement la List
.
Créez un LinkedList
, qui supporte plus rapidement remove
.
_List<String> list = new LinkedList<String>(Arrays.asList(split));
_
split
prenant regexDe l'API:
String.split(String regex)
: scinde cette chaîne en fonction des correspondances de la donnée expression régulière .
_|
_ est un métacaractère regex; si vous souhaitez fractionner un littéral _|
_, vous devez l'échapper à _\|
_, lequel littéral Java est _"\\|"
_.
_template.split("\\|")
_
Au lieu d'appeler remove
avec des index aléatoires, il est préférable de générer suffisamment de nombres aléatoires dans la plage, puis de parcourir la List
avec une listIterator()
, en appelant remove()
aux indices appropriés. Il y a des questions sur stackoverflow sur la façon de générer des nombres aléatoires mais distincts dans une plage donnée.
Avec cela, votre algorithme serait O(N)
.
Celui-ci m'a brûlé plusieurs fois. Arrays.asList
crée une liste non modifiable. Depuis la Javadoc: Renvoie une liste à taille fixe sauvegardée par le tableau spécifié.
Créez une nouvelle liste avec le même contenu:
newList.addAll(Arrays.asList(newArray));
Cela créera une petite poubelle supplémentaire, mais vous pourrez le muter.
Probablement parce que vous travaillez avec wrapper non modifiable .
Changer cette ligne:
List<String> list = Arrays.asList(split);
à cette ligne:
List<String> list = new LinkedList<>(Arrays.asList(split));
Je pense que remplacer:
List<String> list = Arrays.asList(split);
avec
List<String> list = new ArrayList<String>(Arrays.asList(split));
résout le problème.
La liste renvoyée par Arrays.asList()
pourrait être immuable. Pourriez-vous essayer
List<String> list = new ArrayList(Arrays.asList(split));
Il suffit de lire le JavaDoc pour la méthode asList:
Retourne une {@code List} des objets du tableau spécifié. La taille de la {@code List} ne peut pas être modifiée, c’est-à-dire que l’ajout et la suppression ne sont pas pris en charge, mais les éléments peuvent être définis. La définition d'un élément modifie le tableau sous-jacent.
Cela provient de Java 6, mais il semble que ce soit la même chose pour le Android Java.
EDIT
Le type de la liste résultante est Arrays.ArrayList
, qui est une classe privée dans Arrays.class. En pratique, ce n'est rien qu'une vue en liste sur le tableau que vous avez passé avec Arrays.asList
. Conséquence: si vous modifiez le tableau, la liste est également modifiée. Et comme un tableau n'est pas redimensionnable, l'opération de suppression et d'ajout doit ne pas être prise en charge.
Arrays.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 "non modifiable").
Vous pouvez faire new ArrayList<String>(Arrays.asList(split));
pour créer une copie réelle, mais, vu ce que vous essayez de faire, voici une suggestion supplémentaire (vous avez un algorithme O(n^2)
juste en dessous).
Vous voulez supprimer list.size() - count
(appelons cela k
) des éléments aléatoires de la liste. Il vous suffit de choisir autant d’éléments aléatoires et de les permuter aux positions k
finales de la liste, puis de supprimer toute cette plage (par exemple, en utilisant subList () et clear ()). Cela le transformerait en un algorithme maigre et moyen O(n)
(O(k)
est plus précis).
Mise à jour: Comme indiqué ci-dessous, cet algorithme n'a de sens que si les éléments ne sont pas ordonnés, par exemple. si la liste représente un sac. Si, par contre, la liste a un ordre significatif, cet algorithme ne le conservera pas (l'algorithme des polygélélubrifiants le ferait à la place).
Mise à jour 2: Donc, rétrospectivement, un meilleur algorithme (linéaire, en maintenant l'ordre, mais avec O(n) nombres aléatoires) ressemblerait à 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--;
}
}
J'ai une autre solution à ce problème:
List<String> list = Arrays.asList(split);
List<String> newList = new ArrayList<>(list);
travailler sur newList
;)
Cette exception UnsupportedOperationException survient lorsque vous essayez d'effectuer une opération sur une collection où ce n'est pas autorisé. Dans votre cas, lorsque vous appelez Arrays.asList
, il ne retourne pas Java.util.ArrayList
. Il retourne un Java.util.Arrays$ArrayList
qui est une liste immuable. Vous ne pouvez pas y ajouter et vous ne pouvez pas en retirer.
Oui, sur Arrays.asList
, renvoyant une liste de taille fixe.
Outre l’utilisation d’une liste chaînée, utilisez simplement la liste de méthodes addAll
.
Exemple:
String idList = "123,222,333,444";
List<String> parentRecepeIdList = new ArrayList<String>();
parentRecepeIdList.addAll(Arrays.asList(idList.split(",")));
parentRecepeIdList.add("555");
Liste des auteurs = Tableaux.asList (); // Retourne arraylist immuable Pour rendre la solution modifiable, il faudrait: Arraylist narraylist = new ArrayList (Arrays.asList ());
Vous ne pouvez pas supprimer ni ajouter à une liste de tableaux à taille fixe.
Mais vous pouvez créer votre sous-liste à partir de cette liste.
list = list.subList(0, list.size() - (list.size() - count));
public static String SelectRandomFromTemplate(String template, int count) {
String[] split = template.split("\\|");
List<String> list = Arrays.asList(split);
Random r = new Random();
while( list.size() > count ) {
list = list.subList(0, list.size() - (list.size() - count));
}
return StringUtils.join(list, ", ");
}
* L'autre façon est
ArrayList<String> al = new ArrayList<String>(Arrays.asList(template));
cela va créer ArrayList qui n’a pas une taille fixe comme Arrays.asList
Remplacer
List<String> list=Arrays.asList(split);
à
List<String> list = New ArrayList<>();
list.addAll(Arrays.asList(split));
ou
List<String> list = new ArrayList<>(Arrays.asList(split));
ou
List<String> list = new ArrayList<String>(Arrays.asList(split));
ou (Mieux pour Supprimer des éléments)
List<String> list = new LinkedList<>(Arrays.asList(split));
Voici un extrait de code provenant de tableaux
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
/**
* @serial include
*/
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, Java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;
ainsi, lorsque la méthode asList est appelée, elle renvoie la liste de sa propre version de classe statique privée, qui ne remplace pas add funcion de AbstractList pour stocker un élément dans un tableau. Donc, par défaut, ajouter une méthode dans une liste abstraite lève une exception.
Donc, ce n'est pas une liste de tableaux régulière.
Arrays.asList()
utilise un tableau de taille fixe en interne.
Vous ne pouvez pas ajouter ou supprimer dynamiquement de thisArrays.asList()
Utilisez ceci
Arraylist<String> narraylist=new ArrayList(Arrays.asList());
Dans narraylist
, vous pouvez facilement ajouter ou supprimer des éléments.