Java随机数

Java中获取随机数的方式

经常使用的大概就下面5种

  1. Math.random()

获取随机小数范围:[0.0,1.0) 返回的值是double类型

  1. Random类
  • 构造方法:Random() : 建议使用无参构造方法
  • 方法:int nextInt(int n) : 获取 [0,n) 范围的随机整数
  1. ThreadLocalRandom
  • 创建对象: static ThreadLocalRandom current()
  • 方法:int nextInt(int a,int b) : 获取 [a,b) 范围的随机整数
  1. System.currentTimeMillis()
  2. UUID类
  • 静态方法:static UUID randomUUID():获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。即获取随机的字符串,该字符串每次获取都不会重复

Math.random()

  1. 在j2se中使用Math.random()令系统随机选取一个0~1之间的double类型小数,将其乘以一个数,比如25,就能得到一个[0,25)范围内的随机数;Math.round()是四舍五入的意思
  2. 通过Math.random()来获取随机数。实际上,它返回的是0(包含)到1(不包含)之间的double值。使用方法
    如下:
final double d = Math.random();
  1. 若要获取int类型的整数,只需要将上面的结果转行成int类型即可。比如,获取[0, 100)之间的int整数。方法如下:
final double d = Math.random();
final int i = (int)(d*100);

Random类

通过Random类来获取随机数。

使用方法如下:
(01) 创建Random对象。有两种方法可以创建Random对象,如下:

Random random = new Random();//默认构造方法
Random random = new Random(1000);//指定种子数字

(02) 通过Random对象获取随机数。Random支持的随机值类型包括:boolean, byte, int, long, float, double。
比如,获取[0, 100)之间的int整数。方法如下:

int i2 = random.nextInt(100);

Random 的函数接口

// 构造函数(一): 创建一个新的随机数生成器。 
Random() 
// 构造函数(二): 使用单个 long 种子创建一个新随机数生成器: public Random(long seed) { setSeed(seed); } next 方法使用它来保存随机数生成器的状态。
Random(long seed) 

boolean nextBoolean()         // 返回下一个“boolean类型”伪随机数。 
void    nextBytes(byte[] buf) // 生成随机字节并将其置于字节数组buf中。 
double  nextDouble()          // 返回一个“[0.0, 1.0) 之间的double类型”的随机数。 
float   nextFloat()           // 返回一个“[0.0, 1.0) 之间的float类型”的随机数。 
int     nextInt()             // 返回下一个“int类型”随机数。 
int     nextInt(int n)        // 返回一个“[0, n) 之间的int类型”的随机数。 
long    nextLong()            // 返回下一个“long类型”随机数。 
synchronized double nextGaussian()   // 返回下一个“double类型”的随机数,它是呈高斯(“正常地”)分布的 double 值,其平均值是 0.0,标准偏差是 1.0。 
synchronized void setSeed(long seed) // 使用单个 long 种子设置此随机数生成器的种子。

获取随机数示例

public class RandomTest{
 
     public static void main(String args[]){
 
         // 通过System的currentTimeMillis()返回随机数
         testSystemTimeMillis();
 
         // 通过Math的random()返回随机数
         testMathRandom();
 
         // 新建“种子为1000”的Random对象,并通过该种子去测试Random的API
         testRandomAPIs(new Random(1000), " 1st Random(1000)");
         testRandomAPIs(new Random(1000), " 2nd Random(1000)");
         // 新建“默认种子”的Random对象,并通过该种子去测试Random的API
         testRandomAPIs(new Random(), " 1st Random()");
         testRandomAPIs(new Random(), " 2nd Random()");
     }
 
     /**
      * 返回随机数-01:测试System的currentTimeMillis()
      */
     private static void testSystemTimeMillis() {
         // 通过
         final long l = System.currentTimeMillis();
         // 通过l获取一个[0, 100)之间的整数
         final int i = (int)( l % 100 );
 
         System.out.printf("\n---- System.currentTimeMillis() ----\n l=%s i=%s\n", l, i);
     }
 
 
     /**
      * 返回随机数-02:测试Math的random()
      */
     private static void testMathRandom() {
         // 通过Math的random()函数返回一个double类型随机数,范围[0.0, 1.0)
         final double d = Math.random();
         // 通过d获取一个[0, 100)之间的整数
         final int i = (int)(d*100);
 
         System.out.printf("\n---- Math.random() ----\n d=%s i=%s\n", d, i);
     }
 
 
     /**
      * 返回随机数-03:测试Random的API
      */
     private static void testRandomAPIs(Random random, String title) {
         final int BUFFER_LEN = 5;
 
         // 获取随机的boolean值
         boolean b = random.nextBoolean();
         // 获取随机的数组buf[]
         byte[] buf = new byte[BUFFER_LEN];
         random.nextBytes(buf);
         // 获取随机的Double值,范围[0.0, 1.0)
         double d = random.nextDouble();
         // 获取随机的float值,范围[0.0, 1.0)
         float f = random.nextFloat();
         // 获取随机的int值
         int i1 = random.nextInt();
         // 获取随机的[0,100)之间的int值
         int i2 = random.nextInt(100);
         // 获取随机的高斯分布的double值
         double g = random.nextGaussian();
         // 获取随机的long值
         long l = random.nextLong();
 
         System.out.printf("\n---- %s ----\nb=%s, d=%s, f=%s, i1=%s, i2=%s, g=%s, l=%s, buf=[",
                 title, b, d, f, i1, i2, g, l);
         for (byte bt:buf) 
             System.out.printf("%s, ", bt);
         System.out.println("]");
     }
 }

ThreadLocalRandom

在多线程下,使用 java.util.Random 产生的实例来产生随机数是线程安全的,但深挖 Random 的实现过程,会发现多个线程会竞争同一 seed 而造成性能降低。ThreadLocalRandom是一个可以独立使用的、用于生成随机数的类。继承自Random,但性能超过Random,所谓“青出于蓝而胜于蓝”。其API所提供方法,不多,父类Random具有的,它也一样具有。

多线程下获取[1,100)的随机数,如下代码

import java.util.concurrent.ThreadLocalRandom;

public class ThreadLocalRandomDemo {

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Player().start();
        }
    }

    private static class Player extends Thread {
        @Override
        public void run() {
            System.out.println(getName() + ": " + ThreadLocalRandom.current().nextInt(1,100));
        }
    }
}

任何情况下都不要在多个线程间共享一个Random实例,而该把它放入ThreadLocal之中

System.currentTimeMillis()

在System类中有一个currentTimeMillis()方法,这个方法返回从1970年1月1号0点0分0秒到目前的一个long型的毫秒数,可作为一个随机数,还可以将其对某些数取模,就能限制随机数的范围;此方式在循环中同时产生多个随机数时,会是相同的值,有一定的局限性!

//获取一个[min,max]区间内的随机整数
long randomNum = System.currentTimeMillis();
int randomNumber = (int) randomNum%(max-min+1)+min;

UUID类

UUID 是指Universally Unique Identifier,翻译为中文是通用唯一识别码, 其目的,是让分布式系统中的所有元素,都能有唯一的辨识信息。
据说世界可以为世界的每一粒沙子分配一个UUID, 还不会重复

输入的格式是: UUID 的十六个八位字节被表示为 32个十六进制数字,以连字号分隔的五组来显示,形式为 8-4-4-4-12,总共有 36个字符(即三十二个英数字母和四个连字号)。例如:123e4567-e89b-12d3-a456-426655440000

使用很简单,如下即可

String uuid = UUID.randomUUID().toString()

随机指定范围内N个不重复的数的实现方法

/**
 * 随机指定范围内N个不重复的数
 * 利用HashSet的特征,只能存放不同的值
 * @param min 指定范围最小值
 * @param max 指定范围最大值
 * @param n 随机数个数
 * @param HashSet<Integer> set 随机数结果集
*/
public static void randomSet(int min, int max, int n, HashSet<Integer> set) {
    if (n > (max - min + 1) || max < min) {
      return;
    }
    for (int i = 0; i < n; i++) {
      // 调用Math.random()方法
      int num = (int) (Math.random() * (max - min)) + min;
      set.add(num);// 将不同的数存入HashSet中
    }
    int setSize = set.size();
    // 如果存入的数小于指定生成的个数,则调用递归再生成剩余个数的随机数,如此循环,直到达到指定大小
    if (setSize < n) {
    randomSet(min, max, n - setSize, set);// 递归
    }
}

评论

企鹅群:39438021

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×