对于Java来说,生成随机数的方式大概有三种,分别是:通过Math类生成、通过Random类生成和通过ThreadLocalRandom类生成。其中Random和ThreadLocalRandom的使用方式几乎一样,只不过两者使用的场景不一样而已,其中ThreadLocalRandom在多线程中效率更好。
通过Math类型生成
关于Math类,我已经在我的过去的文章中有过介绍,这里就不过多提及。这里只说一个方法,也就是:Math.random()方法。
对于Math.random()生成的是一个0-1之间的double类型的随机浮点数。
关于使用Math.random()方法生成随机数的示例代码如下所示:
public class RandomTest { public static void main(String[] args) { for (int i = 0; i < 5; i++) { System.out.println("第" + i + "次生成的随机数为:" + Math.random()); } } }
执行结果如下图所示:
由于Math.random()只能生成0-1之间的随机数,如果我们想要生成指定范围的随机数,还得加上点算术运算。比如要生成m到n之间的随机数(m <n),那么我首先需要生成0-(n-m)之间的随机数,然后用生成后的随机数再加上m,就可得到所需要的结果。当然,得到的结果是double类型的浮点数,你可以根据需要进行类型强转成对应的类型。
关于使用Math.random()生成指定范围随机数的示例代码如下所示:
public class RandomTest { public static void main(String[] args) { // 生成10在4-8范围内从随机数 for (int i = 0; i < 10; i++) { System.out.println("第" + (i + 1) + "次生成的随机数为:" + random(4, 8)); } } // 生成指定范围的随机数 private static double random(int start, int limit) { if (limit <= 0) { limit = 1; } return Math.random() * (limit - start) + start; } }
执行结果如下图与所示:
通过Random类生成
生成随机数还可以通过Random类来进行生成。对于Random来说,有两个构造器,分别如下:
- public Random():无参构造器,默认使用当前系统时间来计算种子
- public Random(long seed):带参构造器,需自行传入种子。
因为Random生成的是一个伪随机序列,因此当不同的Random对象的种子相同时,就会产生相同的结果。
示例代码如下图所示:
public class RandomTest { public static void main(String[] args) { Random r1 = new Random(50); Random r2 = new Random(50); for (int i = 0; i < 5; i++) { System.out.println("r1的第" + (i + 1) + "次生成的随机数为:" + r1.nextInt()); System.out.println("r2的第" + (i + 1) + "次生成的随机数为:" + r2.nextInt()); } } }
执行结果如下图所示:
通过对比我们可以发现,虽然r1和r2是两个不同的random对象,但是当两者的种子相同时,调用顺序一致时,产生的结果也一致。
- nextXXX之类的方法
Random的nextXXX之类的方法有:
- public void nextBytes(byte[] bytes):生成一个byte数组的随机数
- public int nextInt():随机生成一个整数
- public int nextInt(int bound):随机生成一个在bound范围内的整数
- public boolean nextBoolean():随机生成一个布尔值
- public double nextDouble():随机生成一个double类型的浮点值
- public float nextFloat() :随机生成一个float类型的浮点值
- public long nextLong():随机生成一个long类型的整数值
- public synchronized double nextGaussian():随机生成一个高斯数
关于random对象的nextXXX系列的方法使用示例代码如下所示:
public class RandomTest { public static void main(String[] args) { Random random = new Random(); for (int i = 0; i < 5; i++) { // 随机生成一个字节数组 byte[] bytes = new byte[8]; random.nextBytes(bytes); System.out.println("第" + (i + 1) + "次随机生成的字节数组为:" + Arrays.toString(bytes)); // 生成随机整数 System.out.println("第" + (i + 1) + "次随机生成的整数为:" + random.nextInt()); // 生成一个指定范围的随机整数 System.out.println("第" + (i + 1) + "次随机生成的在10以内的整数为:" + random.nextInt(10)); // 随机生成long类型的整数 System.out.println("第" + (i + 1) + "次随机生成的long类型的整数为:" + random.nextLong()); // 随机生成的float类型的浮点数 System.out.println("第" + (i + 1) + "次随机生成的float类型的浮点数为:" + random.nextFloat()); // 随机生成double类型的浮点数 System.out.println("第" + (i + 1) + "次随机生成的double类型的浮点数为:" + random.nextDouble()); // 随机生成布尔值 System.out.println("第" + (i + 1) + "次随机生成的布尔值为:" + random.nextBoolean()); // 随机生成的高斯数 System.out.println("第" + (i + 1) + "次随机生成的高斯数为:" + random.nextGaussian()); if (i < 4) { System.out.println("========================================="); } } } }
执行结果如下图所示:
- ints方法
Random对象的ints方法生成是一个随机数的IntStream流对象。其大概有四个重载方法:
- public IntStream ints():获取一个随机整数流。该方法需要配合limit方法来使用,否则会一直生成下去。
- public IntStream ints(long streamSize):获取一个指定长度的整数流对象。
- public IntStream ints(int randomNumberOrigin, int randomNumberBound):获取一个在指定范围内的整数流,该方法也需要配合limit方法来进行使用,否则也会一直生成下去。
- public IntStream ints(long streamSize, int randomNumberOrigin, int randomNumberBound):获取一个在指定范围内的指定个数的整数流对象。
关于ints方法使用示例代码如下所示:
public class RandomTest { public static void main(String[] args) { Random random = new Random(); int[] randArr1 = random.ints().limit(5).toArray(); System.out.println(Arrays.toString(randArr1)); int[] randArr2 = random.ints(5).toArray(); System.out.println(Arrays.toString(randArr2)); int[] randArr3 = random.ints(2, 8).limit(5).toArray(); System.out.println(Arrays.toString(randArr3)); int[] randArr4 = random.ints(5, 2, 8).toArray(); System.out.println(Arrays.toString(randArr4)); } }
执行结果如下图所示:
- longs方法
Random对象的longs方法生成是一个随机数的LongStream流对象。其大概有四个重载方法:
- public LongStream longs():返回一个随机的long类型的整数流,需要配置limit方法进行使用。
- public LongStream longs(long streamSize):返回指定个数的long类型的整数流。
- public LongStream longs(long randomNumberOrigin, long randomNumberBound):返回一个指定范围的随机long类型整数流,需要配置limit进行使用。
- public LongStream longs(long streamSize, long randomNumberOrigin, long randomNumberBound):返回一个指定范围的指定个数的long类型整数流。
关于Random的longs方法使用示例代码如下所示:
public class RandomTest { public static void main(String[] args) { Random random = new Random(); long[] randArr1 = random.longs().limit(5).toArray(); System.out.println(Arrays.toString(randArr1)); long[] randArr2 = random.longs(5).toArray(); System.out.println(Arrays.toString(randArr2)); long[] randArr3 = random.longs(2, 8).limit(5).toArray(); System.out.println(Arrays.toString(randArr3)); long[] randArr4 = random.longs(5, 2, 8).toArray(); System.out.println(Arrays.toString(randArr4)); } }
执行结果如下图所示:
- doubles方法
Random对象的longs方法生成是一个随机数的LongStream流对象。其大概有四个重载方法:
- public DoubleStream doubles():返回一个随机的double类型的浮点数流,需配合limit进行使用。
- public DoubleStream doubles(long streamSize):返回一个指定个数的double类型的浮点数流。
- public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound):返回一个指定范围的double类型的浮点数流,需配合limit进行使用。
- public DoubleStream doubles(long streamSize, double randomNumberOrigin,double randomNumberBound):返回一个指定范围的指定个数的double类型的浮点数流。
doubles的示例代码如下所示:
public class RandomTest { public static void main(String[] args) { Random random = new Random(); double[] randArr1 = random.doubles().limit(5).toArray(); System.out.println(Arrays.toString(randArr1)); double[] randArr2 = random.doubles(5).toArray(); System.out.println(Arrays.toString(randArr2)); double[] randArr3 = random.doubles(2, 8).limit(5).toArray(); System.out.println(Arrays.toString(randArr3)); double[] randArr4 = random.doubles(5, 2, 8).toArray(); System.out.println(Arrays.toString(randArr4)); } }
执行结果如下图所示:
通过ThreadLocalRandom类生成
对于ThreadLocalRandom来说,其使用和Random差不多, 区别在于ThreadLocalRandom在多线程环境下,可以更好减少共享资源的竞争。由于ThreadLocalRandom的使用和Random都差不多,这里就展开来说。仅仅提供一个例子演示一下即可。
使用ThreadLocalRandom的示例代码如下所示:
public class RandomTest { public static void main(String[] args) { ThreadLocalRandom random = ThreadLocalRandom.current(); for (int i = 0; i < 5; i++) { System.out.println("第" + (i + 1) + "次获取的随机数为:" + random.nextInt()); } } }
执行结果如下图所示:
自此关于Java中获取随机数的常用方式就已经介绍完毕。