Kotlinでリストを複製またはコピーする方法


102

Kotlinでリストをコピーする方法は?

私は使っています

val selectedSeries = mutableListOf<String>()
selectedSeries.addAll(series)

もっと簡単な方法はありますか?


1
ディープクローニングが必要ない場合のために、あなたのソリューションはすでに最も簡単な方法だと思います。
SerdarSamancıoğlu19年

回答:


144

これは正常に動作します。

val selectedSeries = series.toMutableList()

6
val selectedSeries = series.toList()またtoMutableList()、その実装を呼び出すため、機能します。
フラビオファリア

4
FlávioFaria@だけでそれをテストした===と言っているtoList()コレクションをコピーするのではなく、toMutableList()ない
ペパーミント水田

3
@PeppermintPaddyそれはない空のリストの場合を除いて、コピーを。ソースが空の場合Iterable.toList()emptyList()、常に同じ(不変)オブジェクトを返すを返します。したがって、テストするとemptyList()、同じオブジェクトが返されます。
ローレンスゴンサルベス

52
私は個人的にはこの考えが好きではありません... toMutableList()メソッドを呼び出すインスタンスがすでに変更可能なリストである場合、リストの新しいインスタンスを返すはずのdocs Grantには何もありません。
BrunoJCM

4
これは良い答えではありませんし、間違いなく正しい答えでもありません。このメソッド呼び出しが常に新しいコピーを返すことが明確に文書化されていない限り、将来の実装が変更される可能性はありません。
Bhargav

23

使用できます

リスト-> 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

14

私は2つの代替方法を考え出すことができます:

1. val selectedSeries = mutableListOf<String>().apply { addAll(series) }

2. val selectedSeries = mutableListOf(*series.toTypedArray())

更新:新しい型推論エンジン(Kotlin 1.3のオプトイン)を使用すると、最初の例でジェネリック型パラメーターを省略でき、次のようになります。

1. val selectedSeries = mutableListOf().apply { addAll(series) }

参考:新しい推論をオプトインする方法はkotlinc -Xnew-inference ./SourceCode.kt、コマンドラインまたはkotlin { experimental { newInference 'enable'}Gradleです。新しい型推論の詳細については、このビデオを確認してください:KotlinConf 2018-Svetlana Isakovaによる新しい型推論と関連言語機能、特に「30歳のビルダーの推論」


最初の答えは正しいと思うので、私は2つの答えに分けるべきです。後者は、いくつかの美しさに欠けています。
Holger Brandl 2018

@Jacob Wu:2番目のソリューションの*記号がエラーを生成しないことに驚いた。それは何をするためのものか?「単項乗算」で検索しましたが何も見つかりませんでした。
Lensflare 2018年

1
@Lensflare *は、配列を個別の項目に分解することを意味します。たとえば、mutableListOf(* [1、2、3])はmutableListOf(1、2、3)を意味します。これは、varargの反対の操作のようなものです
Jacob Wu

1
@ジェイコブ呉:ありがとう。あなたの答えで、オペレーターは「スプレッドオペレーター」と呼ばれていることがわかりました。一部のパラメーターを配列と組み合わせてvarargsリストにすることで、それがどのように役立つかがわかります。しかし、それはあなたの例にどのような利点がありますか?それはもっと速いですか、それとも何かですか?それとも、コレクションを確実にコピーするための鍵ですか?
Lensflare 2018年

@Lensflareメリットは構文だけであると思います-コードは短く、明示的なジェネリック型は必要ありません(最初の例のように)。舞台裏では、コードは配列演算用にコンパイルされているので、パフォーマンスは同じになるはずです。
Jacob Wu


9

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)ので、そうではありませんか?それか、それとも?thisapplymutableListOf<T>().also { it.addAll(this) }
Franko LeonTokalić

5

浅いコピーの場合は、

.map{it}

これは、多くのコレクションタイプで機能します。


1
Maps では機能しないことに注意してください。これはコンパイルが、以来itMap.Entry、コピーは浅いですが、あなたは同じエントリを持っています。
noamtm

1
@noamtmはい、それは浅いコピーで私が意味するものです。このメソッドはエントリをコピーしません。同じエントリを持つコレクションのコピーのみを作成します。地図は特別なものではありません。
Lensflare

2
私の要点は、それをマップでも使用するのは魅力的であり、コンパイルして機能するように見えても、実際には機能しないということです。
noamtm

4

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のコピーコンストラクターに依存しているため、他のターゲットでも機能するかどうかはわかりません。


2

私が使用する拡張メソッドをtoCollection()

val original = listOf("A", "B", "C")
val copy = original.toCollection(mutableListOf())

これにより新しいものが作成され、MutableList元の各要素が新しく作成されたリストに追加されます。

ここで推定される型はになりますMutableList<String>。この新しいリストの可変性を公開したくない場合は、タイプを不変リストとして明示的に宣言できます。

val copy: List<String> = original.toCollection(mutableListOf())

0

単純なリストの場合、上記の多くの正しい解決策があります。

ただし、浅いリストの場合のみです。

以下の関数は、任意の2次元で機能しますArrayListArrayList実際には、と同等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



-1

Kotlinでリストをコピーするための以下のコードを試してください

arrayList2.addAll(arrayList1.filterNotNull())
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.