Ich habe diesen 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, ", ");
}
Ich verstehe das:
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)
Wie wäre das der richtige Weg? Java.15
Antworten:
Einige Probleme mit Ihrem Code:
Bei
Arrays.asList
Rückgabe einer Liste mit fester GrößeAus der API:
Sie können nicht
add
dazu; du kannst nichtremove
davon. Sie können das nicht strukturell ändernList
.Fix
Erstellen Sie eine
LinkedList
, die schneller unterstütztremove
.Bei der
split
Einnahme von RegexAus der API:
|
ist ein Regex-Metazeichen; Wenn Sie ein Literal aufteilen möchten|
, müssen Sie es maskieren\|
, was als Java-String-Literal gilt"\\|"
.Fix:
Auf besseren Algorithmus
Anstatt einzeln
remove
mit zufälligen Indizes aufzurufen , ist es besser, genügend Zufallszahlen im Bereich zu generieren und diese dannList
einmal mit a zu durchlaufenlistIterator()
undremove()
entsprechende Indizes aufzurufen . Es gibt Fragen zum Stapelüberlauf, wie zufällige, aber unterschiedliche Zahlen in einem bestimmten Bereich generiert werden können.Damit wäre Ihr Algorithmus
O(N)
.quelle
Random
jedes Mal eine neue Instanz erstellen. Machen Sie es zu einemstatic
Feld und säen Sie es nur einmal.Dieser hat mich oft verbrannt.
Arrays.asList
erstellt eine nicht veränderbare Liste. Aus dem Javadoc: Gibt eine Liste mit fester Größe zurück, die vom angegebenen Array unterstützt wird.Erstellen Sie eine neue Liste mit demselben Inhalt:
Dies wird ein wenig zusätzlichen Müll erzeugen, aber Sie können ihn mutieren.
quelle
Wahrscheinlich, weil Sie mit arbeiten modifizierbaren Wrapper arbeiten .
Ändern Sie diese Zeile:
zu dieser Zeile:
quelle
unmodifiable
undimmutable
.unmodifiable
bedeutet genau "veränderbar, aber nicht strukturell".unmodifiableList
Wrapper zu erstellen und einenset
; es wirftUnsupportedOperationException
. Ich bin mir ziemlich sicher, dass esCollections.unmodifiable*
wirklich volle Unveränderlichkeit bedeutet, nicht nur strukturelle.Ich denke, dass das Ersetzen:
mit
behebt das Problem.
quelle
Die von zurückgegebene Liste ist
Arrays.asList()
möglicherweise unveränderlich. Könnten Sie es versuchenquelle
Lesen Sie einfach das JavaDoc für die asList-Methode:
Dies ist aus Java 6, aber es sieht so aus, als ob es für Android Java dasselbe ist.
BEARBEITEN
Der Typ der resultierenden Liste
Arrays.ArrayList
ist eine private Klasse in Arrays.class. In der Praxis ist es nichts anderes als eine Listenansicht des Arrays, mit dem Sie übergeben habenArrays.asList
. Mit der Konsequenz: Wenn Sie das Array ändern, wird auch die Liste geändert. Und weil ein Array nicht vergrößerbar ist, entfernen und Addierungsoperation müssen nicht mehr unterstützt.quelle
Arrays.asList () gibt eine Liste zurück, die keine Operationen zulässt, die sich auf die Größe auswirken (beachten Sie, dass dies nicht mit "nicht modifizierbar" identisch ist).
Sie können
new ArrayList<String>(Arrays.asList(split));
eine echte Kopie erstellen, aber wenn Sie sehen, was Sie tun möchten, finden Sie hier einen zusätzlichen Vorschlag (Sie haben eineO(n^2)
Algorithmus direkt darunter).Sie möchten zufällige Elemente aus der Liste entfernen
list.size() - count
(nennen wir diesk
).k
Wählen Sie einfach so viele zufällige Elemente aus und tauschen Sie sie an die Endpositionen der Liste aus. Löschen Sie dann den gesamten Bereich (z. B. mit subList () und clear ()). Das würde es zu einem schlanken und mittlerenO(n)
Algorithmus machen (O(k)
ist genauer).Update : Wie unten erwähnt, ist dieser Algorithmus nur dann sinnvoll, wenn die Elemente ungeordnet sind, z. B. wenn die Liste eine Tasche darstellt. Wenn andererseits die Liste eine aussagekräftige Reihenfolge hat, würde dieser Algorithmus diese nicht beibehalten (der Algorithmus der Polygenschmierstoffe würde dies stattdessen tun).
Update 2 : Rückblickend wäre ein besserer Algorithmus (linear, Beibehaltung der Reihenfolge, aber mit O (n) Zufallszahlen) ungefähr so:
quelle
ArrayList
. Viel einfacher als mein Vorschlag. Ich denke, es würde jedoch zu einer Neuordnung der Elemente führen.Ich habe eine andere Lösung für dieses Problem:
Arbeit an
newList
;)quelle
Diese UnsupportedOperationException tritt auf, wenn Sie versuchen, eine Operation für die Sammlung auszuführen, bei der dies nicht zulässig ist, und in Ihrem Fall, wenn Sie sie aufrufen
Arrays.asList
, wird a nicht zurückgegebenjava.util.ArrayList
. Esjava.util.Arrays$ArrayList
wird eine unveränderliche Liste zurückgegeben. Sie können es nicht hinzufügen und nicht entfernen.quelle
Ja, weiter
Arrays.asList
wird eine Liste mit fester Größe zurückgegeben.Verwenden Sie einfach eine verknüpfte Liste
addAll
Methodenliste.Beispiel:
quelle
Ersetzen
zu
oder
oder
oder (Besser zum Entfernen von Elementen)
quelle
Arraylist narraylist = Arrays.asList (); // Unveränderliche Arrayliste zurückgeben Um sie veränderlich zu machen, wäre die Lösung: Arraylist narraylist = new ArrayList (Arrays.asList ());
quelle
Es folgt ein Codeausschnitt aus Arrays
Wenn also die asList-Methode aufgerufen wird, gibt sie eine Liste ihrer eigenen privaten statischen Klassenversion zurück, die die Add-Funktion von AbstractList zum Speichern des Elements im Array nicht überschreibt. Standardmäßig löst die Methode add in der abstrakten Liste eine Ausnahme aus.
Es handelt sich also nicht um eine reguläre Array-Liste.
quelle
Sie können keine Arrays mit fester Größe entfernen oder zu einer Liste mit fester Größe hinzufügen.
Sie können jedoch Ihre Unterliste aus dieser Liste erstellen.
list = list.subList(0, list.size() - (list.size() - count));
* Anderer Weg ist
Dadurch wird eine ArrayList erstellt, deren Größe nicht wie bei Arrays.asList festgelegt ist
quelle
Arrays.asList()
verwendet intern ein Array mit fester Größe.Sie können dies nicht dynamisch hinzufügen oder entfernen
Arrays.asList()
Benutze das
In können
narraylist
Sie einfach Elemente hinzufügen oder entfernen.quelle
Das Erstellen einer neuen Liste und das Auffüllen gültiger Werte in eine neue Liste hat bei mir funktioniert.
Code-Wurffehler -
Nach dem Fix -
quelle