日常开发中少不了产生随机数,本文就分别给大家总结一下Javah和Kotlin中常用的Random方式
简介
随机数是专门的随机试验的结果.
大部分计算机上的伪随机数,并不是真正的随机数,只是重复的周期比较大的数列,是按一定的算法和种子值生成的。
生成真随机数
著名的 Random.org 网站可以用来生成真随机数。它是通过大气噪音 (Atmospheric Noise)生成随机数,由爱尔兰都柏林三一学院Mads Haahr博士于1998创建。
random和urandom设备
/dev/random和/dev/urandom是Linux系统中提供的随机伪设备,这两个设备的任务,是提供永不为空的随机字节数据流。
1. Java 方式
1.1 Math.random()
Math类(java.lang.Math)中的random方法可以产生一个 [0.0,1.0) 之间的类型为double的随机数.
1 | public static void main(String[] args) { |
1.2 Random类
1.2.1 关于初始化和种子
随机种子(Random Seed)是计算机专业术语,一种以随机数作为对象的以真随机数(种子)为初始条件的随机数。
Random类包含两个构造函数:
- 默认构造函数采用以当前时间为种子的方式。
- 指定种子的构造方式相同种子数的Random对象,相同次数生成的随机数字是完全相同的。如:
1
2Random random1 = new Random();
Random random2 = new Random(100);1
2
3
4
5
6
7
8
9
10public static void main(String[] args) {
Random random = new Random(100);
Random random2 = new Random(100);
System.out.println( random.nextInt());
System.out.println( random2.nextInt());
}
Result:
-1193959466
-1193959466
1.2.2 成员方法
返回类型 | 函数名 | 含义 |
---|---|---|
boolean | nextBoolean() | 返回下一个伪随机数它是取自此随机数生成器序列的均匀分布的boolean值。 |
void | nextBytes(byte[] bytes) | 生成随机字节并将其置于用户提供的 byte 数组中。 |
double | nextDouble() | 产生一个在0.0和1.0之间均匀分布的 double随机值。 |
float | nextFloat() | 产生一个在0.0和1.0之间均匀分布的 float随机值。 |
double | nextGaussian() | 返回double随机数,它是呈高斯(“正态”)分布的,其平均值是0.0标准差是1.0。 |
int | nextInt() | 产生一个均匀分布的 int 随机值。 |
int | nextInt(int n) | 产生一个在(包括和指定值(不包括)之间均匀分布的int值。 |
long | nextLong() | 产生一个均匀分布的 int 随机值。long 值。 |
void | setSeed(long seed) | 使用单个 long 种子设置此随机数生成器的种子 |
1.2.3 Math.random()实现
Math.random()方法是调用了 Random的nextDouble 产生的随机double值, 此方法需要注意的是如果连续调用两次,则可能产生相同的随机数,其原因可能因为两条指令执行时间太近导致Random的种子一致。
1.2.4 随机数流
Java8中的Random类,增加一个以流的方式读取随机数的方式。
1 | Random random = new Random(); |
其中IntStream LongStream DoubleStream 三个Stream均为Java8特性,提供了range(a,b)、
sum、sorted、limit等方法.
1.3 其他Random类
1.3.1 ThreadLocalRandom
通过官方介绍了解到,Random类是线程安全的,原因是多线程生成random使用的是同一个Random对象,正因为此,多线程生成random会影响系统性能。于是官方推荐了ThreadLocalRandom.
ThreadLocalRandom是结合了TreadLocal和Random,将每个线程中的random对象通过ThreadLocal保存,从而达到互相隔离的目的.
代码示例:
1 | ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current(); //使用current静态方法创建示例 |
注:与Random在使用上不同的是ThreadLocalRandom不能手动设置seed.
1.3.2 SecureRandom
由于上述中种子相同情况下产生的随机数相等的原因。于是处于更高级的随机性,便有了SecureRandom。
SecureRandom产生随机数的原理和Random并无二致,区别在于种子的选取上。 SecureRandom默认读取由/dev/random产生的随机值作为种子,大大增加了破解的难度。实例代码:
1 | SecureRandom secureRandom = new SecureRandom(); |
注:SecureRandom同时也提供了setSeed方法,但官方不推荐使用.
1.3.3 SplittableRandom
这是一个支持并行计算的随机数类,线程不安全。
1 | SplittableRandom splittableRandom = new SplittableRandom(); |
2. Kotlin 方式
由于Kotlin本身可以调用Java类,所以上述的方法都可以在Kotlin中使用,以下介绍Kotlin中独有的方法创建随机数。
2.1 Range类的random
kotlin支持在Range类中直接取出random.其中包括:
- IntRange
- LongRange
- CharRange
代码实例:1
var num =(0..10).random()
2.2 Random类(package: kotlin.random)
Random中提供各种random函数的伴生对象实现:
- Random.nextBits(bitcount): 随机生成不大于二进制位数不大于bitcount的随机数
- Random.nextInt(): 随机生成一个在Int.MIN_VALUE 和 Int.MAX_VALUE 之间的随机数
- Random.nextLong: 随机生成一个Long类型的数值