一、随机数生成
Java中的随机数生成器是通过java.util.Random类实现的。其提供了多种随机数生成方法,如生成整型、浮点型、布尔型等随机数。
Random random = new Random();
int randomInt = random.nextInt(); //生成整型随机数
double randomDouble = random.nextDouble(); //生成浮点型随机数
boolean randomBoolean = random.nextBoolean(); //生成布尔型随机数
上面的代码示例用到了Random类中三种常用的随机数生成方法。其中nextInt方法生成的随机数范围是整型的所有有效取值,即-2147483648到2147483647;nextDouble方法生成的随机数范围是0到1之间的双精度浮点数。
二、随机数种子
Random类的实例化可以不带参数,也可以通过指定一个种子来实现。通过指定同样的种子,可以保证生成的随机数序列一致。
Random random1 = new Random(123);
Random random2 = new Random(123);
System.out.println(random1.nextInt() == random2.nextInt()); //输出true
上面的代码示例中,两个Random对象被指定了同样的种子123。因此,生成的随机数序列相同,因此输出true。
三、随机数应用
随机数在游戏、密码学、模拟实验等领域有着广泛的应用。以下以模拟扑克牌游戏为例,展示随机数的应用方法。
//生成一副扑克牌,共52张
List<String> pokerDeck = new ArrayList<>();
String[] suits = {"Club", "Diamond", "Heart", "Spade"};
String[] ranks = {"Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"};
for (String suit : suits) {
for (String rank : ranks) {
pokerDeck.add(rank + " of " + suit + "s");
}
}
//对扑克牌进行洗牌
Random random = new Random();
for (int i = pokerDeck.size() - 1; i > 0; i--) {
int j = random.nextInt(i + 1);
Collections.swap(pokerDeck, i, j);
}
上面的代码示例用到了随机数和集合相关的操作,生成了一副扑克牌并进行了洗牌操作。其中,Random的nextInt方法用于从剩余牌中随机选取一张牌,将其和当前牌交换位置。经过若干次这样的操作,即可实现扑克牌的洗牌。
四、随机数性能
Random类在多线程场景下使用时存在线程安全问题。因为其内部状态是共享的,多个线程访问时可能导致生成相同的随机数,也可能导致生成不同的随机数序列。
在高性能场景下,可以使用ThreadLocalRandom类替代Random类,其为每个线程维护了单独的随机数生成器,保证了线程安全和高性能。
int randomInt = ThreadLocalRandom.current().nextInt();
上面的代码示例展示了ThreadLocalRandom类生成随机数的方法。其调用静态方法current获取当前线程的随机数生成器,并调用nextInt方法生成随机数。
五、总结
Java中的随机数生成可以通过Random类或ThreadLocalRandom类实现。Random类可以生成多种类型的随机数,并支持指定种子来保证随机数序列一致。ThreadLocalRandom类为多线程场景下生成随机数提供了线程安全和高性能的支持。