val selectedSeries = series.toList()funktioniert auch, weil es toMutableList()in seiner Implementierung aufruft .
Flávio Faria
4
@ FlávioFaria hat es gerade getestet ===und muss sagen toList(), kopiert die Sammlung nicht, toMutableList()tut es aber
Peppermint Paddy
3
@PeppermintPaddy Es wird kopiert, außer bei leeren Listen. Wenn die Quelle leer ist, wird Iterable.toList()zurückgegeben emptyList(), wodurch immer dasselbe (unveränderliche) Objekt zurückgegeben wird. Wenn Sie also mit testen, erhalten emptyList()Sie dasselbe Objekt zurück.
Laurence Gonsalves
51
Ich persönlich mag diese Idee nicht ... Nichts in den Dokumenten gewährt, was toMutableList()eine neue Instanz einer Liste zurückgeben sollte, wenn die Instanz, die die Methode aufruft, bereits eine veränderbare Liste ist.
BrunoJCM
4
Dies ist keine gute Antwort und definitiv nicht die richtige. Es gibt keine Garantie dafür, dass sich zukünftige Implementierungen ändern könnten, es sei denn, es ist ausdrücklich dokumentiert, dass dieser Methodenaufruf immer eine neue Kopie zurückgibt.
Bhargav
23
Sie können verwenden
Liste -> toList ()
Array -> toArray ()
ArrayList -> toArray ()
MutableList -> toMutableList ()
Beispiel:
val array = arrayListOf("1","2","3","4")val arrayCopy = array.toArray()// copy array to other arrayLog.i("---> array ", array?.count().toString())Log.i("---> arrayCopy ", arrayCopy?.count().toString())
array.removeAt(0)// remove first item in array Log.i("---> array after remove", array?.count().toString())Log.i("---> arrayCopy after remove", arrayCopy?.count().toString())
Protokoll drucken:
array:4
arrayCopy:4
array after remove:3
arrayCopy after remove:4
Update: Mit der neuen Type Inference Engine (Opt-In in Kotlin 1.3) können wir den generischen Typparameter im ersten Beispiel weglassen und haben Folgendes:
Zu Ihrer Information: Die Möglichkeit, neue Inferenz zu aktivieren, ist kotlinc -Xnew-inference ./SourceCode.ktfür die Befehlszeile oder kotlin { experimental { newInference 'enable'}für Gradle. Weitere Informationen zur neuen Typinferenz finden Sie in diesem Video: KotlinConf 2018 - Neue Typinferenz und verwandte Sprachfunktionen von Svetlana Isakova , insbesondere 'Inferenz für Builder' bei 30 '
sollte imho in 2 Antworten aufgeteilt werden, da ich denke, dass die erste richtig ist, aber der letzteren etwas Schönheit fehlt.
Holger Brandl
@ Jacob Wu: Ich war überrascht zu sehen, dass das * -Symbol in der zweiten Lösung keinen Fehler verursachte. Was tut es? Ich habe eine Suche mit "unärer Multiplikation" durchgeführt, aber nichts gefunden.
Lensflare
1
@Lensflare * bedeutet, ein Array in separate Elemente zu zerstören, z. B. mutableListOf (* [1, 2, 3]) bedeutet mutableListOf (1, 2, 3), es ist wie die entgegengesetzte Operation zu vararg
Jacob Wu
1
@ Jacob Wu: Danke. Mit Ihrer Antwort konnte ich herausfinden, dass der Operator "Spread Operator" heißt. Ich sehe, wie es hilft, indem einige Parameter mit einem Array in einer Varargs-Liste kombiniert werden. Aber welchen Nutzen hat es in Ihrem Beispiel? Ist es schneller oder so? Oder ist es der Schlüssel, um sicherzustellen, dass die Sammlung kopiert wird?
Lensflare
@Lensflare Ich denke, der Vorteil ist nur die Syntax - der Code ist kurz und es ist kein expliziter generischer Typ erforderlich (wie in meinem ersten Beispiel). Hinter den Kulissen glaube ich, dass der Code für Array-Operationen kompiliert wurde, daher sollte die Leistung gleich sein.
Sie können die bereitgestellte Erweiterung verwenden Iterable.toMutableList(), mit der Sie eine neue Liste erhalten. Leider soll, wie die Unterschrift und die Dokumentation andeuten, sichergestellt werden, dass ein a Iterableist List(genau wie toStringund viele andere to<type>Methoden). Nichts garantiert Ihnen, dass es sich um eine neue Liste handelt. Das Hinzufügen der folgenden Zeile am Anfang der Erweiterung if (this is List) return thisist beispielsweise eine legitime Leistungsverbesserung (wenn sie tatsächlich die Leistung verbessert).
Außerdem ist der resultierende Code aufgrund seines Namens nicht sehr klar.
Ich ziehe es vor, meine eigene Erweiterung hinzuzufügen, um das Ergebnis sicher zu stellen und einen viel klareren Code zu erstellen (genau wie bei Arrays ):
fun<T>List<T>.copyOf():List<T>{val original =thisreturn mutableListOf<T>().apply { addAll(original)}}fun<T>List<T>.mutableCopyOf():MutableList<T>{val original =thisreturn mutableListOf<T>().apply { addAll(original)}}
Beachten Sie, dass dies addAllder schnellste Weg zum Kopieren ist, da System.arraycopybei der Implementierung von das native verwendet wird ArrayList.
Ich mag diese Lösung. Sollte es nicht sein addAll(this@copyOf), denn thisinnen applywird auf die neu erstellte leere Liste verwiesen ? Entweder das oder mutableListOf<T>().also { it.addAll(this) }?
Beachten Sie, dass es für Maps nicht funktioniert . Es wird kompiliert, aber da das ita Map.Entryist und die Kopie flach ist, haben Sie die gleichen Einträge.
Noamtm
1
@noamtm ja, das meine ich mit flacher Kopie. Diese Methode kopiert niemals die Einträge. Es wird nur eine Kopie der Sammlung mit denselben Einträgen erstellt. Karte ist hier nichts Besonderes.
Lensflare
2
Mein Punkt ist, dass, obwohl es verlockend ist, es auch auf Karten zu verwenden, es kompiliert und zu funktionieren scheint - es nicht wirklich funktioniert.
Noamtm
4
Genau wie in Java:
Aufführen:
val list = mutableListOf("a","b","c")val list2=ArrayList(list)
Karte:
val map = mutableMapOf("a" to 1,"b" to 2,"c" to 3)val map2=HashMap(map)
Angenommen, Sie zielen auf die JVM (oder Android) ab. Ich bin nicht sicher, ob es für andere Ziele funktioniert, da es auf den Kopierkonstruktoren von ArrayList und HashMap basiert.
val original = listOf("A","B","C")val copy = original.toCollection(mutableListOf())
Dadurch wird ein neues MutableListElement erstellt und anschließend jedes Element des Originals zur neu erstellten Liste hinzugefügt.
Der hier abgeleitete Typ wird sein MutableList<String>. Wenn Sie die Veränderbarkeit dieser neuen Liste nicht offenlegen möchten, können Sie den Typ explizit als unveränderliche Liste deklarieren:
val copy:List<String>= original.toCollection(mutableListOf())
Für einfache Listen gibt es oben viele richtige Lösungen.
Es ist jedoch nur für flache Listen.
Die folgende Funktion funktioniert für jede 2-dimensionale ArrayList. ArrayListist in der Praxis gleichbedeutend mit MutableList. Interessanterweise funktioniert es nicht, wenn expliziter MutableListTyp verwendet wird. Wenn man mehr Dimensionen benötigt, muss man mehr Funktionen machen.
fun<T>cloneMatrix(v:ArrayList<ArrayList<T>>):ArrayList<ArrayList<T>>{varMatrResult=ArrayList<ArrayList<T>>()for(i in v.indices)MatrResult.add(v[i].clone()asArrayList<T>)returnMatrResult}
Demo für Integer Matrix:
var mat = arrayListOf(arrayListOf<Int>(1,2),arrayListOf<Int>(3,12))var mat2=ArrayList<ArrayList<Int>>()
mat2= cloneMatrix<Int>(mat)
mat2[1][1]=5
println(mat[1][1])
Antworten:
Das funktioniert gut.
quelle
val selectedSeries = series.toList()
funktioniert auch, weil estoMutableList()
in seiner Implementierung aufruft .===
und muss sagentoList()
, kopiert die Sammlung nicht,toMutableList()
tut es aberIterable.toList()
zurückgegebenemptyList()
, wodurch immer dasselbe (unveränderliche) Objekt zurückgegeben wird. Wenn Sie also mit testen, erhaltenemptyList()
Sie dasselbe Objekt zurück.toMutableList()
eine neue Instanz einer Liste zurückgeben sollte, wenn die Instanz, die die Methode aufruft, bereits eine veränderbare Liste ist.Sie können verwenden
Liste -> toList ()
Array -> toArray ()
ArrayList -> toArray ()
MutableList -> toMutableList ()
Beispiel:
Protokoll drucken:
quelle
Ich kann mir zwei alternative Wege einfallen lassen:
Update: Mit der neuen Type Inference Engine (Opt-In in Kotlin 1.3) können wir den generischen Typparameter im ersten Beispiel weglassen und haben Folgendes:
Zu Ihrer Information: Die Möglichkeit, neue Inferenz zu aktivieren, ist
kotlinc -Xnew-inference ./SourceCode.kt
für die Befehlszeile oderkotlin { experimental { newInference 'enable'}
für Gradle. Weitere Informationen zur neuen Typinferenz finden Sie in diesem Video: KotlinConf 2018 - Neue Typinferenz und verwandte Sprachfunktionen von Svetlana Isakova , insbesondere 'Inferenz für Builder' bei 30 'quelle
Wenn Ihre Liste eine Kotlin-Datenklasse enthält , können Sie dies tun
quelle
Sie können die bereitgestellte Erweiterung verwenden
Iterable.toMutableList()
, mit der Sie eine neue Liste erhalten. Leider soll, wie die Unterschrift und die Dokumentation andeuten, sichergestellt werden, dass ein aIterable
istList
(genau wietoString
und viele andereto<type>
Methoden). Nichts garantiert Ihnen, dass es sich um eine neue Liste handelt. Das Hinzufügen der folgenden Zeile am Anfang der Erweiterungif (this is List) return this
ist beispielsweise eine legitime Leistungsverbesserung (wenn sie tatsächlich die Leistung verbessert).Außerdem ist der resultierende Code aufgrund seines Namens nicht sehr klar.
Ich ziehe es vor, meine eigene Erweiterung hinzuzufügen, um das Ergebnis sicher zu stellen und einen viel klareren Code zu erstellen (genau wie bei Arrays ):
Beachten Sie, dass dies
addAll
der schnellste Weg zum Kopieren ist, daSystem.arraycopy
bei der Implementierung von das native verwendet wirdArrayList
.Beachten Sie auch, dass Sie dadurch nur eine flache Kopie erhalten .
quelle
addAll(this@copyOf)
, dennthis
innenapply
wird auf die neu erstellte leere Liste verwiesen ? Entweder das odermutableListOf<T>().also { it.addAll(this) }
?Für eine flache Kopie schlage ich vor
Das funktioniert für viele Sammlungstypen.
quelle
Map
s nicht funktioniert . Es wird kompiliert, aber da dasit
aMap.Entry
ist und die Kopie flach ist, haben Sie die gleichen Einträge.Genau wie in Java:
Aufführen:
Karte:
Angenommen, Sie zielen auf die JVM (oder Android) ab. Ich bin nicht sicher, ob es für andere Ziele funktioniert, da es auf den Kopierkonstruktoren von ArrayList und HashMap basiert.
quelle
Ich würde die
toCollection()
Erweiterungsmethode verwenden :Dadurch wird ein neues
MutableList
Element erstellt und anschließend jedes Element des Originals zur neu erstellten Liste hinzugefügt.Der hier abgeleitete Typ wird sein
MutableList<String>
. Wenn Sie die Veränderbarkeit dieser neuen Liste nicht offenlegen möchten, können Sie den Typ explizit als unveränderliche Liste deklarieren:quelle
Für einfache Listen gibt es oben viele richtige Lösungen.
Es ist jedoch nur für flache Listen.
Die folgende Funktion funktioniert für jede 2-dimensionale
ArrayList
.ArrayList
ist in der Praxis gleichbedeutend mitMutableList
. Interessanterweise funktioniert es nicht, wenn expliziterMutableList
Typ verwendet wird. Wenn man mehr Dimensionen benötigt, muss man mehr Funktionen machen.Demo für Integer Matrix:
es zeigt
12
quelle
Sie können den
ArrayList
Konstruktor verwenden:ArrayList(list)
quelle
Versuchen Sie den folgenden Code zum Kopieren der Liste in Kotlin
quelle