List をコピーする
List などのコレクション系のクラスには、toList
や toSet
などの、他の型に変換する拡張関数があります。
これらは変換後の型が変換前の型と同じであっても新しいインスタンスを生成するため、
インスタンスのコピーにも使えます。
val list = listOf('A', 'B')
val copiedList = list.toList()
println("list: $list") // > list: [A, B]
println("copiedList: $copiedList") // > copiedList: [A, B]
val mutableList = mutableListOf('A', 'B')
val copiedMutableList = mutableList.toMutableList()
println("mutableList: $mutableList") // > mutableList: [A, B]
println("copiedMutableList: $copiedMutableList") // > copiedMutableList: [A, B]
mutableList += 'C' // コピー元を変更してもコピー先は影響を受けない。
println("mutableList: $mutableList") // > mutableList: [A, B, C]
println("copiedMutableList: $copiedMutableList") // > copiedMutableList: [A, B]
to〜
と as〜
の違い
toList
や toSet
などの to〜
系の関数は元のオブジェクトとは独立したオブジェクトを生成します。
元のオブジェクトを変更しても生成されたオブジェクトは影響を受けません。
部分再掲:
val mutableList = mutableListOf('A', 'B')
val copiedMutableList = mutableList.toMutableList()
println("mutableList: $mutableList") // > mutableList: [A, B]
println("copiedMutableList: $copiedMutableList") // > copiedMutableList: [A, B]
mutableList += 'C' // コピー元を変更してもコピー先は影響を受けない。
println("mutableList: $mutableList") // > mutableList: [A, B, C]
println("copiedMutableList: $copiedMutableList") // > copiedMutableList: [A, B]
一方、asIterable
や asSequence
などの as〜
系の関数が生成するオブジェクトは元のオブジェクトが変更されるとその影響を受けます。
val mutableList = mutableListOf('A', 'B')
val reversed = mutableList.asReversed()
println("mutableList: $mutableList") // > mutableList: [A, B]
println("reversed: $reversed") // > reversed: [B, A]
mutableList += 'C' // 生成元を変更すると生成先が影響を受ける。
println("mutableList: $mutableList") // > mutableList: [A, B, C]
println("reversed: $reversed") // > reversed: [C, B, A]
to〜
系で生成したオブジェクトは生成元の変更の影響を受けないため安全に扱えます。
しかし生成されたオブジェクトも全ての要素の値・参照を持つため、メモリを喰いますし、生成に時間がかかります。
as〜
系で生成したオブジェクトは生成元の変更に追従するため、追従する必要がないときに使うと思わぬバグを生むことになります。
しかし軽量です。
違いを理解して適切に使い分けましょう。