Java 解惑:Random 种子的作用、含参与不含参构造函数区别

Random 通常用来作为随机数生成器,它有两个构造方法:

        Random random = new Random();
        Random random2 = new Random(50);

1.不含参构造方法:

public Random() {
    setSeed(System.nanoTime() + seedBase);
    ++seedBase;
}

2.含参构造方法:

public Random(long seed) {
    setSeed(seed);
}

都调用的 setSeed 方法:

public synchronized void setSeed(long seed) {
    this.seed = (seed ^ multiplier) & ((1L << 48) - 1);
    haveNextNextGaussian = false;
}

可以看到,不含参构造方法每次都使用当前时间作为种子,而含参构造方法是以一个固定值作为种子

什么是种子 seed 呢?

seed 是 Random 生成随机数时使用的参数:

Random 中最重要的就是 next(int) 方法,使用 seed 进行计算:

protected synchronized int next(int bits) {
    seed = (seed * multiplier + 0xbL) & ((1L << 48) - 1);
    return (int) (seed >>> (48 - bits));
}

其他 nextXXX 方法都是调用的 next()。

比如 nextInt(int):

public int nextInt(int n) {
    if (n <= 0) {
        throw new IllegalArgumentException("n <= 0: " + n);
    }
    if ((n & -n) == n) {
        //调用 next()
        return (int) ((n * (long) next(31)) >> 31);
    }
    int bits, val;
    do {
        bits = next(31);
        val = bits % n;
    } while (bits - val + (n - 1) < 0);
    return val;
}

再比如 nextBoolean():

//也是调用的 next()
public boolean nextBoolean() {
    return next(1) != 0;
}

举个栗子:

@Test
public void testRandomParameter(){
    System.out.println("Random 不含参构造方法:");
    for (int i = 0; i < 5; i++) {
        Random random = new Random();
        for (int j = 0; j < 8; j++) {
            System.out.print(" " + random.nextInt(100) + ", ");
        }

        System.out.println("");
    }

    System.out.println("");

    System.out.println("Random 含参构造方法:");
    for (int i = 0; i < 5; i++) {
        Random random = new Random(50);
        for (int j = 0; j < 8; j++) {
            System.out.print(" " + random.nextInt(100) + ", ");
        }
        System.out.println("");
    }
}

分别用含参构造方法和不含参构造方法创建 5 个随机生成器对象,每个随机生成器再生产 8 个随机数,对比下结果:

再运行一次:

总结:

通过上述例子可以发现:

随机数是种子经过计算生成的

  • 不含参的构造函数每次都使用当前时间作为种子,随机性更强
  • 而含参的构造函数其实是伪随机,更有可预见性

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏我和未来有约会

简练的视图模型 ViewModel

patterns & practices Developer Center 发布了 Unity Application Block 1.2 for Silver...

2339
来自专栏前端儿

Web 前端颜色值--字体--使用,整理整理

颜色值 CSS 颜色使用组合了红绿蓝颜色值 (RGB) 的十六进制 (hex) 表示法进行定义。对光源进行设置的最低值可以是 0(十六进制 00)。最高值是 2...

2732
来自专栏一个会写诗的程序员的博客

java.base.jmod

/Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home/jmods$ jmod list java....

1172
来自专栏技术之路

wpf键盘记录器

很简单的一个wpf键盘记录器 ? 这个程序我一样用了全局勾子,之前用的都是winform上运行了,前一段时间 在国外的论坛上逛看到了一个wpf能用的就做了一个小...

2055
来自专栏MelonTeam专栏

Bitmap 源码阅读笔记

导语: Android 系统上的图片的处理,跟Bitmap 这个类脱不了关系,我们有必要去深入阅读里面的源码,以便在工作中能更好的处理Bitmap相关的问题...

2608
来自专栏Ryan Miao

ehcache报错

jfinal2.0+tomcat7+ehcache2.6.11+Linux Linux version 2.6.18-164.el5 (mockbuild@x8...

3749
来自专栏跟着阿笨一起玩NET

c# 使用timer定时器操作,上次定时到了以后,下次还未执行完怎么处理

------解决方案-------------------------------------------------------- 开始的时候,禁用定时器,你...

3011
来自专栏Golang语言社区

Knapsack problem algorithms for my real-life carry-on knapsack

I'm a nomad and live out of one carry-on bag. This means that the total weight o...

1182
来自专栏余生开发

echarts太阳分布图-饼图来回穿梭

var dom = document.getElementById("container");

1392
来自专栏搞前端的李蚊子

Html5模拟通讯录人员排序(sen.js)

// JavaScript Document  var PY_Json_Str = ""; var PY_Str_1 = ""; var PY_Str_...

6326

扫码关注云+社区