LoginSignup
3
0

More than 3 years have passed since last update.

[Kotlin] toList()でMutableListをimmutableなListにする

Posted at

概要

mutableListをListにする時は、必ずしも toList() を呼ぶ必要はないです

fun returnsImmutableList(): List<Int> {
    val mutableList = mutableListOf<Int>()

    // (略:mutableListに要素を詰める)

    return mutableList.toList() // <- ここで無駄に処理が走る
}

説明

mutableListをListにしたい時にとりあえずtoList()を呼びがちですが、無駄に計算量を増やしている場合があります
本稿ではtoList()の挙動について説明し、その使い所について考えます

ListとMutableListの関係

ListMutableListinterfaceで、多くの場合ArrayListを実体として持つと思います

例えば、mutableListOf() はArrayListを生成して返す関数です1

そして、MutableListListを継承しています2

つまり、以下のような記述が可能です

val list: List<Int> = mutableListOf<Int>()

toList()は何をしているか

toList()Iterableインターフェースの関数です

その実装をみてみると、実は内部でtoMutableList()を呼んでいます3
初めの例ですと、MutableListをListにしようとしたのに、実はMutableListを返しているのです

そのtoMutableList()は何をしているかというと、ArrayListのコンストラクタを呼び出して新しいインスタンスを生成します

Collections.kt
public fun <T> Collection<T>.toMutableList(): MutableList<T> {
    return ArrayList(this)
}

この時、元のCollectionはディープコピーされますので、O(N)の時間/空間計算量かかってしまいます

toList()の使い所

以上から、toList()を使う/使わないは次のように判断できます

  • MutableListの参照だけ渡せれば良い場合 -> List型に安全にキャストできる
  • ディープコピーが必要な場合 -> toList()を使う

具体的に書き下すと以下のような使い分けが良さそうです

toList()を使わない

  • 関数の中ではMutableListで扱いたいが、List型として返したい(最初の例)
    • MutableList型のままreturnできます
  • 関数呼び出しで引数としてList型を要求されているが、MutableListを渡したい
    • MutableList型のまま渡せます

toList()を使うべき

  • MutableListを操作したいが操作前の状態を保持したい時
  • Setなど他のCollectionListにする時

以上です
読んでいただきありがとうございました


  1. arrayListOf()で明示的にArrayListを得ることもできます 

  2. https://qiita.com/opengl-8080/items/36351dca891b6d9c9687#%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9%E3%81%AE%E9%96%A2%E4%BF%82 

  3. IterableがCollectionである場合で、かつそのCollectionのsizeが2以上の場合に限ります 

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0