Antworten:
Das funktioniert gut.
val selectedSeries = series.toMutableList()
val selectedSeries = series.toList()
funktioniert auch, weil es toMutableList()
in seiner Implementierung aufruft .
===
und muss sagen toList()
, kopiert die Sammlung nicht, toMutableList()
tut es aber
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.
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:
val array = arrayListOf("1", "2", "3", "4")
val arrayCopy = array.toArray() // copy array to other array
Log.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
Ich kann mir zwei alternative Wege einfallen lassen:
1. val selectedSeries = mutableListOf<String>().apply { addAll(series) }
2. val selectedSeries = mutableListOf(*series.toTypedArray())
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:
1. val selectedSeries = mutableListOf().apply { addAll(series) }
Zu Ihrer Information: Die Möglichkeit, neue Inferenz zu aktivieren, ist kotlinc -Xnew-inference ./SourceCode.kt
fü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 '
Wenn Ihre Liste eine Kotlin-Datenklasse enthält , können Sie dies tun
selectedSeries = ArrayList(series.map { it.copy() })
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 Iterable
ist List
(genau wie toString
und 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 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 ):
fun <T> List<T>.copyOf(): List<T> {
val original = this
return mutableListOf<T>().apply { addAll(original) }
}
fun <T> List<T>.mutableCopyOf(): MutableList<T> {
val original = this
return mutableListOf<T>().apply { addAll(original) }
}
Beachten Sie, dass dies addAll
der schnellste Weg zum Kopieren ist, da System.arraycopy
bei der Implementierung von das native verwendet wird ArrayList
.
Beachten Sie auch, dass Sie dadurch nur eine flache Kopie erhalten .
addAll(this@copyOf)
, denn this
innen apply
wird auf die neu erstellte leere Liste verwiesen ? Entweder das oder mutableListOf<T>().also { it.addAll(this) }
?
Für eine flache Kopie schlage ich vor
.map{it}
Das funktioniert für viele Sammlungstypen.
Map
s nicht funktioniert . Es wird kompiliert, aber da das it
a Map.Entry
ist und die Kopie flach ist, haben Sie die gleichen Einträge.
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.
Ich würde die toCollection()
Erweiterungsmethode verwenden :
val original = listOf("A", "B", "C")
val copy = original.toCollection(mutableListOf())
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:
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
. ArrayList
ist in der Praxis gleichbedeutend mit MutableList
. Interessanterweise funktioniert es nicht, wenn expliziter MutableList
Typ verwendet wird. Wenn man mehr Dimensionen benötigt, muss man mehr Funktionen machen.
fun <T>cloneMatrix(v:ArrayList<ArrayList<T>>):ArrayList<ArrayList<T>>{
var MatrResult = ArrayList<ArrayList<T>>()
for (i in v.indices) MatrResult.add(v[i].clone() as ArrayList<T>)
return MatrResult
}
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])
es zeigt 12
Sie können den ArrayList
Konstruktor verwenden:ArrayList(list)