【Kotlin入門】forEachを完全に理解して使いこなすまでを優しく解説


KotlinでforEachの使い方がわからない
forとforEachの違いがわからない
forEachのループからうまく抜け出せない

KotlinでforEachを書こうと思っても基本的な使い方がわからなかったり、詳しくわかっておらずなぜかループから抜け出せれないという人はいませんか?

こんにちは!エンジニアのかいです。Kotlinをこれから始めようとしている人、もしくは始めたての人であればプログラミングの基本中の基本であるforEachについて上記のような悩みを抱えている人も多いのではないでしょうか。

そこで本日はKotlin初心者の方を対象にforEachの基本的な使い方を説明していきます。基本的な使い方に加えループの抜け出し方や、そのときに使うlabelと概念についても説明していきます。

この記事はこんな人のために書きました。

  • KotlinをはじめたばかりなのでforEachの書き方、使い方がわからない
  • forとforEachの使い方がわからない
  • forEachのループからうまく抜け出せない
  • labelの使い方がよくわからない

KotlinのforEachとは

さて、実際に使い方を紹介して行く前にそもそもKotlinのforEachとはなんなのかという基本的な内容をおさらいしておきましょう。forEachとはリストの要素を一つずつ取り出して処理を行うループ処理のためのものです。

例えば配列の数値の全てに1を足したい場合や、配列の中に特定の文字列が存在するかなどを確認するときに使うこともできますね。言葉で説明するよりも実際のコードを見た方がわかりやすいと思うので紹介していきます。

基本的な使い方をみてみよう

fun main() {
    val numbers = arrayOf(1, 2, 3, 4, 5)

    numbers.forEach{ i ->
        println(i)
    }

    numbers.forEach{
        println(it)
    }
}
1
2
3
4
5
1
2
3
4
5

いきなりコードを書きましたが、KotlinではforEachでは上記のように書きます。ここで注目していただきたのは、1回目のforEachではこのようにiを持たせていますが、2回目では持たせていませんね。

Kotlinではこのように、明示的に変数に格納もできれば、暗黙的にitという変数に格納することもできます。つまり、書かなかったらitに代入されるということですね。

少し詳しい話をすると、->という記法はラムダ式といい、ラムダ式は(メソッドの引数) -> {処理}という風に書くことができます。そして、その引数が一つの場合はitに置き換えることができるようにKotlinではなっているんですね。

forEachから抜け出す方法

次はこちらの例をみてください。

fun main() {
    (1..10).forEach [email protected] {
        println(it)
        if (it == 7) {
            [email protected]
        }
    }

    println("done")
}

このコード、結果はどのようになると思いますか?答えは以下の通りです。

1
2
3
4
5
6
7
8
9
10
done

7までで表示したあと、doneが出て終わると思った方も多いのではないでしょうか。これがKotlin始めたての方がよくしてしまう間違えやすいポイントです。

labelの意味を知ろう

この原因を解明するための前提条件をしっかりと理解しておきます。まず[email protected]ってなんだ?と思った方もいるかもしれませんが、これはlabelと呼ばれるものです。

labelとは、Kotlinにおける任意の式をマークできるもので、この場合では、forEach文をマークしているということですね。そして[email protected]でforEachから抜けようとしています。

ちなみにforEachなどの単純式ではこのように明示的にlabelをつけることはあまりなく、以下のような暗黙のラベルといって、もともと決まっているラベルを使う方が便利です。

fun main() {
    (1..10).forEach{
        println(it)
        if (it == 7) {
            [email protected]
        }
    }
}
1
2
3
4
5
6
7
8
9
10
done

とはいえ、結果は同じですね。

ジャンプ演算子の種類

次にジャンプ演算子の種類を確認しておきます。Kotlinには構文をジャンプするための演算子はreturn, break, continueの3が用意されており、定義は以下のとおりです。

return: 関数を終わらせる
break: 最も近いループを終わらせる
continue: 最も近いループの外側のループの次のステップに進む

forEachではbreakやcontinueは使えない

ちなみにこの説明を受けて、なぜ上のコードではbreakなどを使わずにlabelを使っていたかという疑問が出る人もいるかもしれませんが、結論からいえば、forEachではbreakやcontinueは使えないので同様の処理はreturnやlabelを使って行う必要があるからです。

なぜfor文では使えてforEachでは使えないかという点に関しては、forは構文で、forEachは関数だからです。もっとわかりやすくいえば、forは構文としてbreakやcontinueが設計されていますが、forEachは標準ライブラリでサポートされた関数なのです。

関数の中でbreakなんてみたことないですよね。上記でも説明した通り関数を終わらせる演算子はreturnだけです。

なぜ思い通りの挙動にならなかったのか

さて、ここまできて「1から7が表示されてdoneが表示される」というのが思い通りの挙動としたときになぜそうならなかったか考えてみましょう。

fun main() {
    (1..10).forEach{
        println(it)
        if (it == 7) {
            [email protected]
        }
    }

    println("done")
}

このコードでは[email protected]に実質、breakを期待していますよね。forEachをreturnで終わらせているのでそのように動く気もします。

ですがこれは実際には、[email protected]はcontinueであるためこのような挙動になっているのですね。では、どのようにかけばbreakとして機能してくれるのでしょうか。

fun main() {
    run {
        (1..10).forEach {
            println(it)
            if (it == 7) {
                [email protected]
            }
        }
    }

    println("done")
}

答えはこのようにrunという関数で囲ってあげてrun関数をreturnしてやれば良いです。

1
2
3
4
5
6
7
done

まとめ

今日はforEachの使い方を学んできました。

forEachでかけることは全てforで書き換えることができ、forの方が早いので推奨という声もありますが、両方の使い方や違い、はまりポイントをしっかり理解しておくことも今後必要になってくるのでfor文しか知らないのではなく、forEach文もしっかりと理解しておきましょう。

for文に関するリンクは以下にはっておきますね。

それでは!!

【Kotlin入門】for, whileを学んでループ処理をマスターしよう!
更新日 : 2019年6月19日
LINEで送る
Pocket

SEからWebエンジニアへ転職した理由

侍エンジニア塾卒業生の小池さんは、以前は社内SEとして約5年ほど勤務していました。しかし業務内容は社内のヘルプデスク対応など、プログラムを書く仕事は全くなかったそうです。

SEながらプログラムを書けない現状に「将来仕事がなくなるんじゃないか」と不安を感じ、プログラミング学習を決意。

弊社スクールで学習し、無事ベンチャー企業のプログラマーとして転職に成功しました。そんな小池さんの学習法や転職体験談を伺いましたので、是非ご覧ください。

「プログラミングができないSEは仕事がなくなる」不安を感じたSEが未経験から転職成功するまで
更新日 : 2019年10月7日

書いた人

かい

かい

日向徹かこよすぎか

[email protected]

おすすめコンテンツ

あなたにぴったりなプログラミング学習プランを無料で診断!

プログラミング学習の効率を劇的に上げる学習メソッドを解説