Kotlinには標準で kotlin.random.Random が用意されており、数値生成や抽選処理、テスト用データの作成など、さまざまな場面で利用されます。
一方で、使い方を誤ると「意図しない範囲の値が出る」「テストが不安定になる」「セキュリティ事故につながる」といった問題を引き起こします。
本記事では、KotlinのRandomを正しく、安全に使うための知識を基礎から実務レベルまで丁寧に解説します。
KotlinのRandomとは何か
kotlin.random.Random は、疑似乱数生成器(PRNG) を抽象化したクラスです。
import kotlin.random.Random
- Kotlin 1.3 以降で標準提供
- JVM / Android / Kotlin Multiplatform で共通のAPI
- プラットフォームごとに最適な実装が内部で選ばれる
Java の java.util.Random よりも、APIが簡潔で安全に使いやすい設計になっています。
基本的な乱数生成
数値型ごとの生成
val i = Random.nextInt()
val l = Random.nextLong()
val d = Random.nextDouble()
生成される範囲は以下の通りです。
| メソッド | 範囲 |
|---|---|
| nextInt() | Int.MIN_VALUE ~ Int.MAX_VALUE |
| nextLong() | Long.MIN_VALUE ~ Long.MAX_VALUE |
| nextDouble() | 0.0 ≤ x < 1.0 |
nextDouble() は 1.0を含まない点に注意してください。
範囲を指定する(最も使用頻度が高い)
Random.nextInt(0, 10) // 0~9
Random.nextLong(5, 20) // 5~19
Random.nextDouble(1.5, 3.0)
Kotlinの乱数APIは 半開区間 [from, until) を採用しています。
- 開始値(from)は含まれる
- 終了値(until)は含まれない
これは until を使ったレンジ指定と同じ思想です。
Booleanと確率処理
単純な真偽値
Random.nextBoolean()
確率を指定した判定
val isHit = Random.nextDouble() < 0.3 // 30%の確率でtrue
抽選ロジックやゲーム判定では、この形が最もシンプルで安全です。
コレクションとRandomの組み合わせ
ランダムに要素を取得
val list = listOf("A", "B", "C")
val item = list.random()
random() は内部的に Random.Default を使用します。
Randomを指定して取得(再現性が必要な場合)
val random = Random(1234)
val item = list.random(random)
- テスト
- シミュレーション
- バグ再現
このような用途では 必ずRandomを外部から渡すのがベストプラクティスです。
シャッフル
val shuffled = list.shuffled()
または
val random = Random(42)
val shuffled = list.shuffled(random)
Random.Default と シード付きRandomの違い
Random.Default
Random.nextInt()
- 実行ごとに異なる結果
- 通常のアプリ・UI・ゲーム向け
- 並行実行でも問題が起きにくい設計
日常的な用途では、基本的にこれを使えば問題ありません。
シード付きRandom(再現性あり)
val random = Random(100)
println(random.nextInt())
println(random.nextInt())
- 同じシード → 同じ乱数列
- テストの安定化
- ロジック検証に必須
JUnitテストやロジック検証では、シード固定が強く推奨されます。
JavaのRandomとの違い
Kotlinでは、新規コードで kotlin.random.Random を使うのが基本です。
| 項目 | Kotlin Random | java.util.Random |
|---|---|---|
| APIの簡潔さ | ◎ | △ |
| 範囲指定 | nextInt(from, until) | 手動計算 |
| Multiplatform | ◎ | ✕ |
| コレクション連携 | ◎ | ✕ |
既存Javaコードとの互換が必要な場合のみ、java.util.Random を使います。
セキュリティ用途では使ってはいけない
これは非常に重要なポイントです。
kotlin.random.Random は 暗号学的に安全ではありません。
以下の用途には使えません。
- パスワード
- 認証トークン
- 招待コード
- APIキー
- ワンタイムコード
JVM環境では、必ず SecureRandom を使用します。
import java.security.SecureRandom
val secureRandom = SecureRandom()
val bytes = ByteArray(32)
secureRandom.nextBytes(bytes)
Android / Composeでの注意点
再Composeで値が変わる問題
@Composable
fun MyScreen() {
val value = Random.nextInt() // 再Composeのたびに変わる
}
対策(画面表示中だけ固定)
val value = remember { Random.nextInt() }
さらに寿命を長くしたい場合
- 画面回転まで保持 →
rememberSaveable - アプリロジックとして保持 →
ViewModel
よくある落とし穴
上限が含まれると勘違いする
Random.nextInt(1, 6) // 1~5
サイコロなら:
Random.nextInt(1, 7)
毎回Randomを生成してしまう
repeat(1000) {
val r = Random(System.currentTimeMillis().toInt())
r.nextInt()
}
- 短時間で似たシードになる
- 分布が偏る
- 無駄なオブジェクト生成
正しい使い方
repeat(1000) {
Random.nextInt()
}
または再現性が必要な場合
val random = Random(42)
repeat(1000) {
random.nextInt()
}
実務でよく使うパターン
簡易的な抽選処理
fun isWin(rate: Double): Boolean {
require(rate in 0.0..1.0)
return Random.nextDouble() < rate
}
ランダムカラー生成
val color = Color(
Random.nextInt(256),
Random.nextInt(256),
Random.nextInt(256)
)
仮ID生成(非セキュア用途)
val id = Random.nextLong().toString(16)
※ 負数・桁数不定・衝突の可能性があるため、一意性や安全性が必要なIDには使わないでください。
まとめ
nextInt(from, until)は untilを含まない- 再現性が必要なら シード付きRandom
- テストではRandomを外部注入する
- セキュリティ用途では 絶対に使わない
- 日常用途では
Random.Defaultで十分
以上、KotlinのRandomの扱い方についてでした。
最後までお読みいただき、ありがとうございました。










