Java 提供 java.util.Random 類與 Math.random() 兩大隨機數 API。本文對比兩者差異,詳解 Random 全方法,並給出生成指定範圍整數/浮點數的標準姿勢。
| 特性 | java.util.Random | Math.random() |
|---|---|---|
| 返回類型 | int, long, float, double, boolean, Gaussian | 僅 double [0.0, 1.0) |
| 種子控制 | 構造函數指定 / setSeed() 可復現 | 無法控制 |
| 執行緒安全 | 方法同步,多執行緒爭用有鎖開銷 | 內部用同步 Random 實例,同樣有鎖 |
| 適用場景 | 需多類型、可控種子、高效能(配合 ThreadLocalRandom) | 簡單臨時需求、單次腳本 |
// 構造
new Random() // 種子 = System.nanoTime()
new Random(long seed) // 固定種子,序列可復現
// 基礎類型
nextInt() // 全 int 範圍
nextInt(int bound) // [0, bound) —— 最常用
nextLong()
nextFloat() // [0.0, 1.0)
nextDouble() // [0.0, 1.0)
nextBoolean()
nextGaussian() // 正態分佈 μ=0, σ=1
// 種子管理
setSeed(long seed) // 重置種子
// 錯誤寫法:new Random().nextInt(max - min + 1) + min // 若 max=Integer.MAX_VALUE 會溢位
// 標準寫法 (Java 8+)
Random r = new Random();
int randomInRange = r.nextInt(max - min + 1) + min; // 安全前提:max-min < Integer.MAX_VALUE
// 更優雅:ThreadLocalRandom (Java 7+),無鎖、效能更高
int random = ThreadLocalRandom.current().nextInt(min, max + 1); // [min, max+1) → [min, max]
double randomDouble = min + (max - min) * new Random().nextDouble();
// 或
double randomDouble = ThreadLocalRandom.current().nextDouble(min, max);
// [min, max] 整數
int n = (int) Math.round(Math.random() * (max - min) + min);
// 注意:Math.round 四捨五入,分佈不如 nextInt 均勻
// 長整型避免溢位
long temp = Math.round(Math.random() * 8999 + 1000); // 1000-9999
Random 為偽隨機(線性同餘演算法),不可用於加密場景**(密碼、Token、Session ID)**。加密級隨機請用 java.security.SecureRandom。
選對工具、守住範圍邊界、警惕執行緒安全與加密誤用,是用好 Java 隨機數的三把鑰匙。