Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

Kotlin辞典

  1. トップページ
  2. Kotlin辞典
  3. シーケンス — 終端操作

シーケンス — 終端操作

Kotlinのシーケンスは終端操作が呼ばれたときに初めて評価されます。『toList()』『first()』『take()』などの終端操作でシーケンスを具体的な値やコレクションに変換します。

構文
val seq = generateSequence(1) { it + 1 }  // 無限シーケンス

// toList — リストに変換します(必ず take で制限します)
val list = seq.take(5).toList()            // [1, 2, 3, 4, 5]

// first / last — 最初/最後の要素
val first = seq.take(10).first()           // 1
val firstEven = seq.first { it % 2 == 0 } // 2

// takeWhile / dropWhile — 条件で制御します。
val lessThan5 = seq.takeWhile { it < 5 }.toList()  // [1, 2, 3, 4]
メソッド一覧
終端操作概要
シーケンス.toList()シーケンス全体をリストに変換します(無限シーケンスは先に take します)。
シーケンス.toSet()セットに変換します。
シーケンス.take(n)先頭 n 件のシーケンスを返します(中間操作でもあります)。
シーケンス.takeWhile { 条件 }条件が true の間の要素を返します。false になったら停止します。
シーケンス.drop(n)先頭 n 件をスキップします。
シーケンス.dropWhile { 条件 }条件が true の間をスキップします。false になったら残りを返します。
シーケンス.first()最初の要素を返します。
シーケンス.first { 条件 }条件に合う最初の要素を返します。
シーケンス.firstOrNull { 条件 }条件に合う最初の要素を返します(なければ null)。
シーケンス.count()要素数を返します(有限シーケンスのみ)。
シーケンス.sum() / average()合計/平均を計算します(有限シーケンスのみ)。
シーケンス.forEach { }各要素で処理を実行します。
サンプルコード
fun main() {
    // 自然数の無限シーケンス
    val naturals = generateSequence(1) { it + 1 }

    // take — 先頭 N 件
    println("先頭10個: ${naturals.take(10).toList()}")

    // takeWhile — 条件が真の間
    println("10未満: ${naturals.takeWhile { it < 10 }.toList()}")

    // drop と take の組み合わせ(ページング)
    val page2 = naturals.drop(10).take(5).toList()  // 11〜15
    println("2ページ目: $page2")

    println()

    // first — 条件を満たす最初の要素
    val firstSquare = naturals.first { it * it > 50 }
    println("50超の最初の平方数: $firstSquare × $firstSquare = ${firstSquare * firstSquare}")

    // firstOrNull — なければ null
    val seq = sequenceOf(1, 3, 5, 7, 9)
    println("偶数: ${seq.firstOrNull { it % 2 == 0 }}")  // null

    println()

    // 素数シーケンス(エラトステネスの簡易版)
    fun primes(): Sequence<Int> = sequence {
        val sieve = mutableSetOf<Int>()
        var n = 2
        while (true) {
            if (n !in sieve) {
                yield(n)
                sieve.addAll(generateSequence(n * n) { it + n }.takeWhile { it < 1000 })
            }
            n++
        }
    }

    println("最初の10個の素数: ${primes().take(10).toList()}")
    println("50以下の素数: ${primes().takeWhile { it <= 50 }.toList()}")

    println()

    // asSequence でリストを効率的に処理します。
    val data = (1..10000).toList()
    val result = data.asSequence()
        .filter { it % 3 == 0 }   // 3の倍数
        .map { it * it }           // 2乗
        .take(5)                   // 最初の5件
        .toList()
    println("3の倍数の2乗(5件): $result")  // [9, 36, 81, 144, 225]
}
概要

『takeWhile()』と『dropWhile()』はシーケンスの条件制御に欠かせません。条件が1回でも偽になると停止(takeWhile)またはスタート(dropWhile)するため、ソート済みデータの範囲抽出や無限シーケンスの制御に適しています。

シーケンスの中間操作(filter/map/take等)はオブジェクトを返し、終端操作(toList/first/count等)は具体的な値を返します。終端操作を呼ぶまで何も処理が走りません。

シーケンスの生成はsequenceOf() / generateSequence()を、コルーチンの非同期ストリームはFlow — 基本を参照してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。