Как скопировать список в Котлине?
я использую
val selectedSeries = mutableListOf<String>()
selectedSeries.addAll(series)
Есть способ попроще?
Ответы:
Это прекрасно работает.
val selectedSeries = series.toMutableList()
val selectedSeries = series.toList()
также работает, потому что требует toMutableList()
своей реализации.
===
и должен сказать , toList()
не копировать коллекции, но toMutableList()
делает
Iterable.toList()
возвращается emptyList()
, который всегда возвращает один и тот же (неизменяемый) объект. Так что если вы попробуете, emptyList()
вы получите тот же объект обратно.
toMutableList()
возвращает новый список: «Возвращает новый MutableList, заполненный всеми элементами этой коллекции».
Ты можешь использовать
Список -> toList ()
Массив -> toArray ()
ArrayList -> toArray ()
MutableList -> toMutableList ()
Пример:
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())
распечатать журнал:
array: 4
arrayCopy: 4
array after remove: 3
arrayCopy after remove: 4
Я могу предложить два альтернативных способа:
1. val selectedSeries = mutableListOf<String>().apply { addAll(series) }
2. val selectedSeries = mutableListOf(*series.toTypedArray())
Обновление: с новым механизмом вывода типа (опция в Kotlin 1.3) мы можем опустить параметр общего типа в 1-м примере и получить следующее:
1. val selectedSeries = mutableListOf().apply { addAll(series) }
FYI. Способ включения нового вывода - kotlinc -Xnew-inference ./SourceCode.kt
для командной строки или kotlin { experimental { newInference 'enable'}
для Gradle. Для получения дополнительной информации о новом выводе типов посмотрите это видео: KotlinConf 2018 - Новый вывод типов и связанные с ним языковые функции от Светланы Исаковой , особенно «вывод для строителей» на 30-й странице.
Если ваш список содержит класс данных kotlin , вы можете сделать это
selectedSeries = ArrayList(series.map { it.copy() })
Вы можете использовать предоставленное расширение, Iterable.toMutableList()
которое предоставит вам новый список. К сожалению, как следует из его подписи и документации , он предназначен для обеспечения того, чтобы объект Iterable
был List
(как toString
и многие другие to<type>
методы). Ничто не гарантирует вам, что это будет новый список. Например, добавив следующую строку в начале расширения:if (this is List) return this
является законным улучшением производительности (если оно действительно улучшает производительность).
Кроме того, из-за своего названия результирующий код не очень понятен.
Я предпочитаю добавить собственное расширение, чтобы быть уверенным в результате и создать гораздо более понятный код (как у нас для массивов ):
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) }
}
Обратите внимание, что addAll
это самый быстрый способ копирования, поскольку он использует собственный System.arraycopy
в реализации ArrayList
.
Также имейте в виду, что это даст вам только поверхностную копию .
addAll(this@copyOf)
, потому что this
внутри apply
будет ссылаться на только что созданный пустой список? Либо так, либо mutableListOf<T>().also { it.addAll(this) }
?
Для мелкой копии я предлагаю
.map{it}
Это будет работать для многих типов коллекций.
Map
s. Он компилируется, но, поскольку it
это a Map.Entry
, а копия неглубокая, у вас есть те же записи.
Как и в Java:
Список:
val list = mutableListOf("a", "b", "c")
val list2 = ArrayList(list)
Карта:
val map = mutableMapOf("a" to 1, "b" to 2, "c" to 3)
val map2 = HashMap(map)
Предполагая, что вы ориентируетесь на JVM (или Android); Я не уверен, что он работает для других целей, поскольку он полагается на конструкторы копирования ArrayList и HashMap.
Я хотел бы использовать в toCollection()
метод расширения :
val original = listOf("A", "B", "C")
val copy = original.toCollection(mutableListOf())
Это создаст новый, MutableList
а затем добавит каждый элемент оригинала во вновь созданный список.
Предполагаемый тип здесь будет MutableList<String>
. Если вы не хотите раскрывать изменчивость этого нового списка, вы можете явно объявить тип как неизменяемый список:
val copy: List<String> = original.toCollection(mutableListOf())
Для простых списков есть много правильных решений выше.
Однако это только для мелководных списков.
Приведенная ниже функция работает для любых двухмерных ArrayList
. ArrayList
на практике эквивалентен MutableList
. Интересно, что это не работает при использовании явного MutableList
типа. Если нужно больше измерений, нужно сделать больше функций.
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
}
Демо для целочисленной матрицы:
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])
это показывает 12
Вы можете использовать ArrayList
конструктор:ArrayList(list)