リスト — forEach() / forEachIndexed()
| 対応: | Kotlin 1.0(2016) |
|---|
Kotlinの『forEach()』はリストの各要素に対してラムダを実行します。『forEachIndexed()』はインデックスと要素を同時に受け取れます。繰り返し処理の基本メソッドです。
構文
val fruits = listOf("りんご", "バナナ", "オレンジ")
// forEach — 各要素で処理を実行します
fruits.forEach { println(it) }
// forEachIndexed — インデックスも使います
fruits.forEachIndexed { index, fruit ->
println("$index: $fruit")
}
// for ループと同等です
for ((index, fruit) in fruits.withIndex()) {
println("$index: $fruit")
}
メソッド一覧
| メソッド | 概要 |
|---|---|
| リスト.forEach { it } | 各要素に対してラムダを実行します。戻り値はありません(Unit)。 |
| リスト.forEachIndexed { i, v -> } | インデックスと要素を引数にラムダを実行します。 |
| リスト.withIndex() | インデックスと要素のペア(IndexedValue)のリストを返します。 |
| リスト.onEach { it } | forEach と同じですが、元のコレクション自身を返します(チェーン可能)。 |
| マップ.forEach { (k, v) -> } | マップのキーと値を分割して受け取ります。 |
サンプルコード
sample_list_foreach.kt
data class Student(val name: String, val score: Int)
fun main() {
val students = listOf(
Student("member_a", 85),
Student("member_b", 72),
Student("member_c", 91),
Student("member_d", 68)
)
// 基本の forEach
println("=== 成績一覧 ===")
students.forEach { student ->
println("${student.name}: ${student.score}点")
}
println()
// forEachIndexed で番号付き出力
println("=== 番号付き ===")
students.forEachIndexed { index, student ->
val rank = index + 1
println("$rank 位 ${student.name}: ${student.score}点")
}
println()
// マップでの forEach(キーと値を分割)
val capitals = mapOf("日本" to "東京", "フランス" to "パリ", "アメリカ" to "ワシントンD.C.")
println("=== 首都一覧 ===")
capitals.forEach { (country, capital) ->
println("$country の首都: $capital")
}
println()
// onEach — forEach と同じですがチェーンできます
val names = students
.onEach { println("処理中: ${it.name}") }
.map { it.name }
println("名前リスト: $names")
println()
// withIndex で for ループ
println("=== withIndex ===")
for ((i, s) in students.withIndex()) {
println("[$i] ${s.name}")
}
}
list_foreach.kt
kotlinc list_foreach.kt -include-runtime -d list_foreach.jar java -jar list_foreach.jar === 成績一覧 === member_a: 85点 member_b: 72点 member_c: 91点 member_d: 68点 === 番号付き === 1 位 member_a: 85点 2 位 member_b: 72点 3 位 member_c: 91点 4 位 member_d: 68点 === 首都一覧 === 日本 の首都: 東京 フランス の首都: パリ アメリカ の首都: ワシントンD.C. 処理中: member_a 処理中: member_b 処理中: member_c 処理中: member_d 名前リスト: [member_a, member_b, member_c, member_d] === withIndex === [0] member_a [1] member_b [2] member_c [3] member_d
よくあるミス
『forEach』の戻り値を使おうとするミスがあります。『forEach』は『Unit』を返すため、変換結果をリストとして得ることはできません。変換結果を集めたい場合は『map』が使えます。
『forEach』の中で『break』しようとするミスもあります。『forEach』はラムダなので『break』・『continue』は使えません。途中で抜けたい場合は通常の『for』ループが使えます。
下記のサンプルコードで、正しい使い方を確認できます。
sample_list_foreach_mistakes.kt
data class Student(val name: String, val score: Int)
fun main() {
val students = listOf(
Student("member_a", 85),
Student("member_b", 72),
Student("member_c", 91),
Student("member_d", 68)
)
// 変換結果が必要なときは map を使う
val names = students.map { it.name }
println("名前: $names")
// ループを抜けたいときは for ループを使う
for (s in students) {
if (s.score >= 90) break
println("90点未満: ${s.name}")
}
// ラムダだけを抜けたいときは return@forEach を使う
students.forEach { s ->
if (s.score < 70) return@forEach // このラムダだけスキップ
println("合格: ${s.name}")
}
// forEachIndexed は index が第1引数
students.forEachIndexed { index, student ->
println("$index: ${student.name}")
}
}
コンパイルして実行すると次のようになります。
kotlinc sample_list_foreach_mistakes.kt -include-runtime -d sample_list_foreach_mistakes.jar java -jar sample_list_foreach_mistakes.jar 名前: [member_a, member_b, member_c, member_d] 90点未満: member_a 90点未満: member_b 合格: member_a 合格: member_b 合格: member_c 0: member_a 1: member_b 2: member_c 3: member_d
概要
『forEach()』は副作用(ログ出力・DBへの書き込みなど)を伴う処理に使います。変換結果が必要な場合は『map()』、条件に合う要素を絞り込む場合は『filter()』を使うと、意図がより明確になります。
『forEach』の中でループを抜け出したい場合は『return@forEach』でラムダからリターンできます(通常の『return』は外側の関数を返します)。ループを完全に中断するには『for』ループと『break』を使います。
リストの基本操作はリスト — 生成 / listOf() / mutableListOf()を、フィルタリングと変換はリスト — filter() / map()を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。