首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 產生指定範圍隨機數完整攻略

     編輯:Java 相關知識

兩大核心類對比

特性java.util.RandomMath.random()
返回類型int/long/float/double/boolean/Gaussian僅 double (0.0~1.0)
種子控制支持指定種子,結果可復現不可控,系統時間種子
線程安全同步方法,多線程有鎖競爭內部同步,同樣有競爭
性能較高,可復用實例每次調用創建 Random 實例
適用場景通用隨機數、需復現、多類型簡單臨時需求、單次調用

Random 核心方法速查

Random random = new Random();           // 系統時間種子
Random random = new Random(100L);       // 指定種子,結果固定

random.nextInt();           // 隨機 int (含負數)
random.nextInt(100);        // [0, 100) 隨機 int
random.nextLong();          // 隨機 long
random.nextDouble();        // [0.0, 1.0) 隨機 double
random.nextFloat();         // [0.0, 1.0) 隨機 float
random.nextBoolean();       // 隨機 boolean
random.nextGaussian();      // 高斯分布 (均值0,標準差1)

常見範圍生成公式

1. [min, max] 閉區間整數

// 方式一:Random.nextInt (推薦)
int randomInt = random.nextInt(max - min + 1) + min;

// 方式二:Math.random
int randomInt = (int) (Math.random() * (max - min + 1)) + min;

// 方式三:ThreadLocalRandom (JDK 7+, 多線程高性能)
int randomInt = ThreadLocalRandom.current().nextInt(min, max + 1);

2. [0, n) 非負整數

int n = 100;
int r1 = random.nextInt(n);           // 最簡潔
int r2 = Math.abs(random.nextInt()) % n; // 兼容舊代碼寫法
int r3 = (int) (Math.random() * n);

3. 指定精度小數


// 保留 2 位小數 [0.00, 100.00]
double r = Math.round(random.nextDouble() * 10000) / 100.0;
// 或
double r = new BigDecimal(random.nextDouble() * 100).setScale(2, RoundingMode.HALF_UP).doubleValue();

進階場景實戰

生成不重複隨機數(如彩票號碼)

public static List<Integer> distinctRandom(int count, int min, int max) {
    if (count > (max - min + 1)) throw new IllegalArgumentException("範圍不足");
    
    Set<Integer> set = new LinkedHashSet<>(); // 保持插入順序
    Random random = new Random();
    while (set.size() < count) {
        set.add(random.nextInt(max - min + 1) + min);
    }
    return new ArrayList<>(set);
}

// JDK 8+ Stream 寫法
public static int[] distinctRandomStream(int count, int min, int max) {
    return ThreadLocalRandom.current()
        .ints(min, max + 1)
        .distinct()
        .limit(count)
        .toArray();
}

加權隨機選擇(如抽獎概率)

public static <T> T weightedRandom(Map<T, Integer> weightMap) {
    int totalWeight = weightMap.values().stream().mapToInt(Integer::intValue).sum();
    int randomWeight = ThreadLocalRandom.current().nextInt(totalWeight);
    
    int cumulative = 0;
    for (Map.Entry<T, Integer> entry : weightMap.entrySet()) {
        cumulative += entry.getValue();
        if (randomWeight < cumulative) {
            return entry.getKey();
        }
    }
    throw new IllegalStateException("權重計算異常");
}

可復現隨機序列(測試/模擬專用)

// 固定種子,每次運行序列相同
Random seededRandom = new Random(12345L);
for (int i = 0; i < 5; i++) {
    System.out.println(seededRandom.nextInt(100));
}
// 輸出固定:51, 78, 12, 34, 90...

線程安全高性能選擇:ThreadLocalRandom

JDK 7 引入 java.util.concurrent.ThreadLocalRandom,每線程獨立實例,無鎖競爭,性能遠超 Random 和 Math.random()。

// 並行流中使用
List<Integer> list = ThreadLocalRandom.current()
    .ints(1000, 1, 101)
    .boxed()
    .collect(Collectors.toList());

安全性警示

Random 非加密安全,種子可預測。安全敏感場景(Token、Session ID、加密密鑰)必須使用:

SecureRandom secureRandom = new SecureRandom();
byte[] token = new byte[32];
secureRandom.nextBytes(token);
String secureToken = Base64.getUrlEncoder().withoutPadding().encodeToString(token);

總結選型建議

  • 一般業務:ThreadLocalRandom.current().nextInt(min, max+1)
  • 需復現測試:new Random(seed)
  • 簡單臨時:(int)(Math.random() * range) + min
  • 加密安全:SecureRandom
  • 並行大量生成:ThreadLocalRandom + Stream API
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved