1. 概要

Kotlin言語では、コレクションを操作する方法としてシーケンスが導入されています。 これらはJavaStreamsと非常によく似ていますが、内部で異なる主要な概念を使用しています。 このチュートリアルでは、シーケンスとは何か、なぜそれらが必要なのかについて簡単に説明します。

2. シーケンスを理解する

シーケンスはコンテナです順序タイプ付き T 。 また、 map() filter()などの中間操作や、 count() find( )

JavaのStreamと同様に、KotlinのSequenceは遅延して実行されます。 違いは、シーケンスを使用して複数の操作を使用してコレクションを処理する場合、各ステップの最後に中間結果が得られないことです。 したがって、各ステップの処理後に新しいコレクションを導入することはありません。

大規模なコレクションを操作しながら、アプリケーションのパフォーマンスを向上させる大きな可能性があります。 一方、小さなコレクションを処理する場合、シーケンスにはオーバーヘッドがあります。

3. シーケンスの作成

3.1. 要素から

要素からシーケンスを作成するには、 sequenceOf()関数を使用します。

val seqOfElements = sequenceOf("first" ,"second", "third")

3.2. 関数から

無限のシーケンスを作成するには、 generateSequence()関数を呼び出すことができます。

val seqFromFunction = generateSequence(Instant.now()) {it.plusSeconds(1)}

3.3. チャンクから

任意の長さのチャンクからシーケンスを作成することもできます。 単一の要素を受け取るyield()と、コレクションを受け取る yieldAll()を使用した例を見てみましょう。

val seqFromChunks = sequence {
    yield(1)
    yieldAll((2..5).toList())
}

ここで言及する価値があるのは、すべてのチャンクが次々に要素を生成するということです。 つまり、無限のコレクションジェネレーターがある場合は、それを最後に配置する必要があります。

3.4. コレクションから

Iterable インターフェイスのコレクションからシーケンスを作成するには、 asSequence()関数を使用する必要があります。

val seqFromIterable = (1..10).asSequence()

4. 怠惰で熱心な処理

2つの実装を比較してみましょう。 シーケンスのない最初のものは熱心です:

val withoutSequence = (1..10).filter{it % 2 == 1}.map { it * 2 }.toList()

そして2番目のシーケンスは怠惰です:

val withSequence = (1..10).asSequence().filter{it % 2 == 1}.map { it * 2 }.toList()

それぞれの場合にいくつの中間コレクションが導入されましたか?

最初の例では、各オペレーターが中間コレクションを導入しています。 したがって、10個の要素すべてが map()関数に渡されます。 2番目の例では、中間コレクションが導入されていないため、map()関数には入力として5つの要素しかありません。

5. 結論

このチュートリアルでは、Kotlinのシーケンスについて簡単に説明しました。 さまざまな方法でシーケンスを作成する方法を見てきました。 また、シーケンスがある場合とない場合のコレクションの処理に違いが見られます。

すべてのコード例は、GitHubから入手できます。