Kotlin の chunked は、コレクションや文字列を扱う際によく使われる便利な拡張関数で、「一定サイズごとに分割する」ことを目的としています。
単なる使い方だけでなく、挙動の前提・注意点・他の関数との違いまで理解しておくと、実務でのバグや設計ミスを防げます。
chunked とは何か(概要)
chunked は Iterable / Sequence / CharSequence(String) に対して使える拡張関数で、
要素を指定したサイズごとの「塊(chunk)」に分割する
ための関数です。
イメージ
[1, 2, 3, 4, 5, 6, 7]
↓ chunked(3)
[[1, 2, 3], [4, 5, 6], [7]]
最後のチャンクは、指定サイズに満たなくても必ず返される点が重要です。
基本的な使い方(List / Iterable)
val list = listOf(1, 2, 3, 4, 5, 6, 7)
val result = list.chunked(3)
println(result)
出力
[[1, 2, 3], [4, 5, 6], [7]]
戻り値の型
List<List<T>>
- 元のコレクション型に関係なく、結果は
List<List<T>> - 元の要素順は 保持される
String(文字列)での chunked
String は CharSequence を実装しているため、そのまま chunked を使用できます。
val text = "KOTLIN"
println(text.chunked(2))
[KO, TL, IN]
日本語文字についての注意点
val text = "こんにちは"
println(text.chunked(2))
[こん, にち, は]
Kotlin の String.chunked は UTF-16 の Char(コード単位) で分割します。
そのため、ひらがな・漢字など一般的な日本語文字は問題になりにくい一方で、
- 絵文字(サロゲートペア)
- 結合文字(見た目1文字だが内部的に複数 Char)
を含む場合は、見た目上の「1文字」単位で分割される保証はありません。
chunked は「文字数」ではなく Char 数で区切る関数である点は、実務では必ず意識しておく必要があります。
transform 付き chunked(非常に重要)
chunked には チャンクごとに変換処理を行うオーバーロードがあります。
chunked(size: Int, transform: (List<T>) -> R): List<R>
例:チャンク単位で合計を計算
val numbers = listOf(1, 2, 3, 4, 5, 6)
val sums = numbers.chunked(2) { chunk ->
chunk.sum()
}
println(sums)
[3, 7, 11]
特徴
- 結果は
List<R>になり、List<List<T>>を最終結果として保持しない - 各チャンク自体は
List<T>として生成されるが、
map + chunked を分けて書くより意図が明確 - 可読性・保守性・パフォーマンスのバランスが良い
※ CharSequence.chunked の transform では、ラムダ引数は CharSequence になります。
chunked と windowed の違い(重要)
| 項目 | chunked | windowed |
|---|---|---|
| 分割方式 | 固定サイズの非重複 | スライド式 |
| 重複 | なし | あり |
| 主な用途 | バッチ処理 | 連続比較・移動処理 |
windowed の例
val list = listOf(1, 2, 3, 4)
println(list.windowed(2))
[[1, 2], [2, 3], [3, 4]]
chunked の場合
[[1, 2], [3, 4]]
補足すると、chunked(size) は概念的にはwindowed(size, step = size, partialWindows = true) の簡易版です。
Sequence と chunked(遅延評価)
val seq = generateSequence(1) { it + 1 }
val result = seq
.chunked(3)
.take(3)
.toList()
println(result)
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Sequence.chunkedは 遅延評価- 無限シーケンスでも
takeなどの終端操作で安全に制御可能 - 大量データ処理やストリーム処理と相性が良い
実務でよくあるユースケース
API のバッチ送信
userIds.chunked(100).forEach { batch ->
sendApi(batch)
}
UI レイアウト用の分割
items.chunked(3).forEach { row ->
// 3列表示
}
固定長データ・CSV処理
val record = "ABCDE12345"
val fields = record.chunked(5)
注意点・落とし穴
サイズは必ず 1 以上
list.chunked(0) // IllegalArgumentException
最後のチャンクはサイズ保証されない
listOf(1,2,3,4,5).chunked(2)
[[1,2],[3,4],[5]]
Set での使用について
Set は 順序を前提としないコレクション型です。setOf() は多くの場合挿入順を保持しますが、型としては保証されていません。
- 順序が重要 →
Listを使う - 明示したい →
toList()で変換する
map + chunked vs chunked(transform)
分離した書き方
list.chunked(3).map { it.sum() }
推奨
list.chunked(3) { it.sum() }
- 中間処理が減る
- 処理意図が明確
- 実務ではこちらが読みやすい
まとめ
chunkedは 一定サイズごとの分割- 最後のチャンクは小さくなる可能性あり
transform付きが実務では特に有用- 文字列では Char(UTF-16)単位で分割される
- 大量データでは
Sequenceと組み合わせると安全
以上、Kotlinのchunkedについてでした。
最後までお読みいただき、ありがとうございました。










