B-Teck!

お仕事からゲームまで幅広く

【Kotlin】Sequenceを使おう

Sequenceとは?

Kotlinにおけるコレクション遅延操作の仕組み。
Java8で導入されたStreamに似ており、各要素を直列に評価したあと、最終的な結果を取得する。
こう書くと難しそうなので、実際のコードを見てもらったほうが早いと思います。

Sequenceを使うと何が嬉しいか

ループ回数が少なくなる

Sequenceを使わない場合

(1..3).map { it * 10 }
      .map { it * 10 }
      .map { it * 10 }

このような処理の場合、通常のCollectionのまま操作を行うと、map毎にループが発生し、Listを生成します。
実際に行われている処理は下記のような感じで、ループ回数は9回、Listは4つ生成されているのがわかりますね。

val list = mutableListOf(1, 2, 3)  
val list2 = list.map { it * 10 }  
val list3 = list2.map { it * 10 }  
val list4 = list3.map { it * 10 }  

Sequenceを使った場合

Sequenceを使った場合は、このように書きます。

(1..3).asSequence()
      .map { it * 10 }
      .map { it * 10 }
      .map { it * 10 }
      .toList()

見た目はほぼ変わらないのですが、実際に行われる処理は全く異なります。

val list = mutableListOf(1, 2, 3)  
val list2 = list.map {  
  val result1 = it * 10  
  val result2 = result1 * 10  
  result2 * 10  
}  
println(list2)  

生成されるListは2つ、ループ回数は3回と、大幅に計算量が減っています。

不要な計算をスキップできる

ループ回数よりもこちらのほうが、計算量に大きな差が出ます。

Sequenceを使わない場合

(1..3).map { it * 10 }
      .map { it * 10 }
      .map { it * 10 }
      .first{ it == 2000 }

このような処理の場合、first() の手前まですべての要素を処理してから結果を生成します。
実際に行われている処理は下記のような感じで、先述した計算に加えて、
first()で2000に行き当たるまでの2回計算回数が増えています。
また、Listも一つ多く生成されて5個になっていますね。

val list = mutableListOf(1, 2, 3)  
val list2 = list.map { it * 10 }  
val list3 = list2.map { it * 10 }  
val list4 = list3.map { it * 10 }  
val list5 = list4.first{ it == 2000 }  

Sequenceを使った場合

Sequenceを使った場合は、このように書きます。

(1..3).asSequence()
      .map { it * 10 }
      .map { it * 10 }
      .map { it * 10 }
      .first{ it == 2000 }

こちらも見た目はほぼ変わらないのですが、実際に行われる処理は全く異なります。

val list = mutableListOf(1, 2, 3)  
val list2 = list.first {  
  val result1 = it * 10  
  val result2 = result1 * 10  
  val result3 = result2 * 10  
  result3 == 2000  
}  
println(list2)  

生成されるListが2つなのは前回と同じですが、この場合なんとループ回数が2回で終わります。
要素をひとつずつ処理するので、 first()take() などのように、
全ての要素を処理する必要がないケースで絶大な効果を発揮するのです。

まとめ

  • Kotlinで、Collectionに対して複数の処理を行う場合は asSequence()Sequence として扱うと良いよ
  • 全ての要素を処理する必要がないケースではほぼ必須レベルだよ

参考