Java Random 类
上次修改时间:2025 年 4 月 20 日
Random 类是 Java 实用程序包的一部分,用于生成伪随机数。它提供了一些方法,可以轻松生成随机整数、双精度浮点数、布尔值和高斯分布的值。
随机数生成对于游戏、模拟、密码学和测试至关重要。 Random 类使用 48 位种子和一个线性同余公式来创建伪随机序列。
Random 类概述
Random 类使用由种子值启动的算法生成伪随机数。相同的种子会产生相同的数字序列,有助于保持测试和调试的一致性。
它包括诸如 nextInt、nextDouble 和 nextBoolean 之类的方法,用于生成各种随机值。 这些方法是线程安全的,但大量争用可能会影响性能。
基本随机数生成
此示例说明了 Random 类的基本用法,用于在一个简单的程序中创建随机整数、双精度浮点数和布尔值。
package com.zetcode;
import java.util.Random;
public class BasicRandom {
public static void main(String[] args) {
Random random = new Random();
// Generate random integer
int randInt = random.nextInt();
System.out.println("Random integer: " + randInt);
// Generate random integer between 0 (inclusive) and 100 (exclusive)
int randIntRange = random.nextInt(100);
System.out.println("Random integer (0-99): " + randIntRange);
// Generate random double between 0.0 and 1.0
double randDouble = random.nextDouble();
System.out.println("Random double: " + randDouble);
// Generate random boolean
boolean randBool = random.nextBoolean();
System.out.println("Random boolean: " + randBool);
}
}
该程序实例化一个 Random 对象以生成四个随机值。 不带参数的 nextInt 方法会生成任何整数,而带有边界时,它会生成从 0 到该边界(不包括)的值。
每次执行都会产生唯一的结果,因为 Random 实例使用当前时间作为其默认种子。 这些值在其各自的范围内均匀分布。
种子随机数生成
此示例显示了如何将固定种子与 Random 类一起使用。特定的种子确保了数字序列的一致性,非常适合用于测试和调试目的。
package com.zetcode;
import java.util.Random;
public class SeededRandom {
public static void main(String[] args) {
// Create two Random instances with the same seed
Random random1 = new Random(42);
Random random2 = new Random(42);
System.out.println("First sequence from random1:");
for (int i = 0; i < 5; i++) {
System.out.println(random1.nextInt(100));
}
System.out.println("\nSecond sequence from random2:");
for (int i = 0; i < 5; i++) {
System.out.println(random2.nextInt(100));
}
}
}
在此,两个 Random 实例使用相同的种子 (42) 初始化。 由于共享的种子值,两者都会生成相同的数字序列。
这种可预测性对于需要可重复结果的应用程序(例如模拟或可重现的游戏状态)至关重要。 如果没有固定种子,每次运行都会产生不同的序列。
生成范围内的随机数
此示例演示了如何在自定义范围内生成随机数,允许生成任何最小值和最大值之间的数字,而不仅仅是从零开始。
package com.zetcode;
import java.util.Random;
public class RandomRange {
public static void main(String[] args) {
Random random = new Random();
int min = 10;
int max = 20;
// Method 1: Using nextInt(bound) with adjustment
int rand1 = random.nextInt(max - min + 1) + min;
System.out.println("Random between " + min + " and " + max + ": " + rand1);
// Method 2: Using doubles for more flexible ranges
double rand2 = min + (max - min) * random.nextDouble();
System.out.println("Random double in range: " + rand2);
}
}
第一种方法使用带有计算边界的 nextInt 来生成包含范围内的整数。公式为 random.nextInt(max - min + 1) + min。
第二种方法使用 nextDouble 生成该范围内的随机双精度浮点数,从而为小数值提供更高的精度。 这两种方法都有效地适用于各种用例。
生成随机字符串
此示例说明了如何使用 Random 类创建随机字符串。 我们实现了一种方法,用于从定义的字符集中生成指定长度的字符串。
package com.zetcode;
import java.util.Random;
public class RandomString {
private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
public static String generateRandomString(Random random, int length) {
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) {
int randomIndex = random.nextInt(CHARACTERS.length());
char randomChar = CHARACTERS.charAt(randomIndex);
sb.append(randomChar);
}
return sb.toString();
}
public static void main(String[] args) {
Random random = new Random();
System.out.println("Random string (8 chars): " + generateRandomString(random, 8));
System.out.println("Random string (12 chars): " + generateRandomString(random, 12));
System.out.println("Random string (16 chars): " + generateRandomString(random, 16));
}
}
我们为随机字符串定义了一个有效字符的常量字符串。 generateRandomString 方法通过从此集合中随机选择字符来构建字符串。
此方法对于创建密码、唯一 ID 或测试数据非常有用。 可以定制字符集,使其仅包含特定应用程序所需的字符。
安全随机数
对于安全关键型任务,Java 提供了 SecureRandom,这是一种密码学上强大的随机数生成器。 此示例显示了其与标准 Random 类相比的用法。
package com.zetcode;
import java.security.SecureRandom;
import java.util.Random;
public class SecureRandomExample {
public static void main(String[] args) {
// Regular Random
Random random = new Random();
System.out.println("Regular Random int: " + random.nextInt());
// SecureRandom
SecureRandom secureRandom = new SecureRandom();
System.out.println("SecureRandom int: " + secureRandom.nextInt());
// Generating a secure random byte array
byte[] randomBytes = new byte[16];
secureRandom.nextBytes(randomBytes);
System.out.print("SecureRandom bytes: ");
for (byte b : randomBytes) {
System.out.printf("%02x", b);
}
System.out.println();
}
}
SecureRandom 提供密码学上强大的随机数,用于生成会话密钥或令牌等任务。 虽然比 Random 慢,但它可以确保更高的随机性。
此示例演示了如何生成整数和字节数组。 字节数组以十六进制显示,以提高清晰度。 对所有加密操作使用 SecureRandom。
Random 与流
Java 8 的流与 Random 类无缝集成。 此示例显示了如何生成具有不同特征的随机数流。
package com.zetcode;
import java.util.Random;
import java.util.stream.IntStream;
import java.util.stream.DoubleStream;
public class RandomStreams {
public static void main(String[] args) {
Random random = new Random();
// Generate stream of random integers
System.out.println("Random integers (limit 5):");
IntStream intStream = random.ints(5);
intStream.forEach(System.out::println);
// Generate stream of random integers in range
System.out.println("\nRandom integers between 50-100 (limit 5):");
IntStream rangeStream = random.ints(5, 50, 100);
rangeStream.forEach(System.out::println);
// Generate stream of random doubles
System.out.println("\nRandom doubles (limit 5):");
DoubleStream doubleStream = random.doubles(5);
doubleStream.forEach(System.out::println);
// Generate infinite stream and limit it
System.out.println("\nRandom Gaussian values (limit 5):");
random.doubles()
.map(d -> random.nextGaussian())
.limit(5)
.forEach(System.out::println);
}
}
此示例介绍了四种创建随机数流的方法。 ints、doubles 和 longs 方法生成原始值的流。
我们展示了具有设定大小的有界流和明确限制的无界流。 最后一个案例生成高斯分布的值,展示了流的随机数功能方法。
性能注意事项
此示例比较了 Random 和 ThreadLocalRandom 在多线程设置中的性能,其中 ThreadLocalRandom 在效率方面表现出色。
package com.zetcode;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
public class RandomPerformance {
static final int COUNT = 10000000;
public static void main(String[] args) {
// Test Random
long start = System.currentTimeMillis();
Random random = new Random();
for (int i = 0; i < COUNT; i++) {
random.nextInt();
}
long duration = System.currentTimeMillis() - start;
System.out.println("Random time: " + duration + "ms");
// Test ThreadLocalRandom
start = System.currentTimeMillis();
for (int i = 0; i < COUNT; i++) {
ThreadLocalRandom.current().nextInt();
}
duration = System.currentTimeMillis() - start;
System.out.println("ThreadLocalRandom time: " + duration + "ms");
}
}
ThreadLocalRandom 通过维护每个线程的单独生成器来优化多线程环境中的随机数生成,从而避免了争用。
输出突出显示了性能差异。 对于并发应用程序,ThreadLocalRandom 更可取,但在单线程情况下,差异很小。
生成随机数组
此示例演示了如何使用 Random 类创建填充了随机数的数组,这对于模拟或测试方案很有用。
package com.zetcode;
import java.util.Arrays;
import java.util.Random;
public class RandomArray {
public static void main(String[] args) {
Random random = new Random();
int size = 10;
// Generate array of random integers
int[] intArray = new int[size];
for (int i = 0; i < size; i++) {
intArray[i] = random.nextInt(100);
}
System.out.println("Random integer array: " + Arrays.toString(intArray));
// Generate array of random doubles
double[] doubleArray = new double[size];
for (int i = 0; i < size; i++) {
doubleArray[i] = random.nextDouble();
}
System.out.println("Random double array: " + Arrays.toString(doubleArray));
}
}
该程序创建两个数组:一个包含随机整数,另一个包含随机双精度浮点数。 每个元素都是使用 Random 类生成的。
这样的数组对于测试算法或模拟数据集很有用。 Arrays.toString 方法格式化输出,以便于阅读。
从列表中随机选择
此示例显示了如何使用 Random 类从列表中随机选择元素,这在游戏或采样应用程序中是一项常见任务。
package com.zetcode;
import java.util.List;
import java.util.Random;
public class RandomSelection {
public static void main(String[] args) {
Random random = new Random();
List<String> items = List.of("Apple", "Banana",
"Orange", "Grape", "Mango");
// Select one random item
int index = random.nextInt(items.size());
String randomItem = items.get(index);
System.out.println("Random item: " + randomItem);
// Select multiple random items (with replacement)
System.out.println("Three random items:");
for (int i = 0; i < 3; i++) {
index = random.nextInt(items.size());
System.out.println(items.get(index));
}
}
}
我们使用 nextInt 在列表的范围内生成一个随机索引,然后检索该索引处的元素以进行单个或多个选择。
此技术适用于游戏中的随机项目选择或采样数据等场景。 该示例包括替换选择,允许重复项目。
生成随机高斯值
此示例探讨了 Random 类生成高斯(正态分布)随机数的能力,这在统计模拟中很有用。
package com.zetcode;
import java.util.Random;
public class RandomGaussian {
public static void main(String[] args) {
Random random = new Random();
// Generate 5 Gaussian random numbers
System.out.println("Gaussian random values (mean 0, std dev 1):");
for (int i = 0; i < 5; i++) {
double gaussian = random.nextGaussian();
System.out.printf("%.4f%n", gaussian);
}
// Scale Gaussian values to custom mean and standard deviation
double mean = 100;
double stdDev = 15;
System.out.println("\nScaled Gaussian values (mean 100, std dev 15):");
for (int i = 0; i < 5; i++) {
double scaled = mean + random.nextGaussian() * stdDev;
System.out.printf("%.4f%n", scaled);
}
}
}
nextGaussian 方法生成平均值为 0,标准偏差为 1 的数字。我们还展示了缩放到自定义平均值和偏差。
这非常适合用于建模自然现象或统计数据。 缩放值演示了如何使高斯数适应特定要求。
来源
本教程全面探讨了 Java Random 类,涵盖了基本用法、种子生成、范围创建、安全选项和性能。 随机数生成对于许多应用程序至关重要。
作者
列出所有Java教程。