Java随机数(实例一步步解剖)

179 阅读6分钟

本文已参与[新人创作礼]活动,一起开启掘金创作之路。

哈喽,大家好!我是Why,一名在读学生,目前刚刚开始进入自己的编程学习生涯。虽然学习起步较晚,但我坚信做了才有0或1的可能。学了一段时间以后也是选择在掘金上分享自己的日常笔记,也希望能够在众多道友的大家庭中打成一片。 本文主要讲解java实现随即数的几种方式,如果大家读后觉得有用的话,还请大家多多支持博主:欢迎 ❤️点赞👍、收藏⭐、留言💬 ✨✨✨个人主页:JinHuan

文章目录


Java中的随机数是怎样产生的呢?

🍎1、Java.Util.Random类

🌾🤡🐢✨🤙💎

util包里面提供的Random类
通过剖析源码发现java.util.Random()有两种构造形式:
        1、Random()
            /**
             * 创建一个新的随机数生成器。
             * 此构造函数将随机数生成器的种子设置为一个很可能与此构造函数的任何其他调用不同的值。
             */
            public Random() {
                this(seedUniquifier() ^ System.nanoTime());
            }
    
        2、Random(long seed)
           /**
             * 使用单个long种子创建新的随机数生成器。种子是通过方法next(int)维护的伪随机数发生器的内部状态的初始值。
			* 调用new Random(seed)相当于:
   			* Random rnd = new Random(); rnd.setSeed(seed); 
             *       参数:seed - 初始种子
             */
            public Random(long seed) {
                if (getClass() == Random.class)
                    this.seed = new AtomicLong(initialScramble(seed));
                else {
                    // subclass might have overriden setSeed
                    this.seed = new AtomicLong();
                    setSeed(seed);
                }
            }
        
'区别:'
       带有种子的Random类实例,如果随机种子相同那么每次随机生成的结果是一样的;
       不带有随机种子的Random实例,每次随机生成的结果都是随机的
'原因:'
    	不带有随机种子的Random类实例,是以当前时间(System.currentTimeMillis()为初始种子的,
    	这个最后有讲解),这个时间永远不可能重复(就像代码自上而下运行,对象也是依次创建)
    	所以不带有随机种子的Random实例每次随机生成的结果都是随机的。

📈实例

import java.util.Random;

/**
 * @Author jinhuan
 * @Date 2022/3/6
 *
 * 实例化两对Random对象,一对带种子、一对不带种子,下面通过代码简单展示二者的区别
 */
public class RandomTest {
    public static void main(String[] args) {
        //实例化带种子的Random对象
        Random random01 = new Random(10);
        //等价于 Random random02 = new Random().setSeed(10);
        Random random02 = new Random(10);

        System.out.println("带相同随机种子的两个Random实例对象:");
        for (int i = 0; i < 3; i++) {
            System.out.println("random01 的第"+(i+1)+"个随机数-->"+random01.nextInt());
            System.out.println("random02 的第"+(i+1)+"个随机数-->"+random02.nextInt());
            System.out.println();
        }

        System.out.println("-----------分界线-------------");

        //实例化不带种子的Random对象
        Random rdm01 = new Random();
        Random rdm02 = new Random();

        System.out.println("不带随机种子的两个Random实例对象:");
        for (int i = 0; i < 3; i++) {
            System.out.println("rdm01 的第"+(i+1)+"个随机数-->"+rdm01.nextInt());
            System.out.println("rdm02 的第"+(i+1)+"个随机数-->"+rdm02.nextInt());
            System.out.println();
        }

    }
}

🥝运行截屏

image-20220310105850366

🌈2、Math.Random类

Java.lang包提供了一个内置的Math类,也为我们提供了生成随机数的内置的静态方法	random();

/**
 * @Author jinhuan
 * @Date 2022/3/12
 *
 * 返回一个带正号的 {@code double} 值, 大于或等于 {@code 0.0} 且小于 {@code 1.0}。
 * 返回值是伪随机选择的,从该范围(近似)均匀分布。
 * <p>当这个方法第一次被调用时,它会创建一个新的伪随机数生成器,
 * 就像通过表达式 <blockquote>{@code new java.util.Random()}<blockquote>
 * 这个新的伪随机数生成器此后用于对该方法的所有调用,并且不用于其他任何地方。
 * <p>此方法已正确同步,以允许多个线程正确使用。
 * 但是,如果许多线程需要以很高的速率生成伪随机数,则可能会减少每个线程对拥有自己的伪随机数生成器的争用。
 * @return 一个大于或等于 {@code 0.0} 且小于 {@code 1.0} 的伪随机 {@code double}。
 */
public static double random() {
        return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble();
}


简单来说,该方法是返回[0,1)之间的一个随机数,返回类型为double
如果要返回整数类型的随机数:
     强制转换数据类型即可,强转后整数的部分会赋值给int类型的变量,小数部分则会丢失
     int intRandom = (int)Math.random();
如果生成【0,n】之间的随机数:
     (Math.random()*(n+1));注意是乘以 n+1
如果要生成【m,n】之间的随机数:
     double temp = m + (Math.random() * (n-m));
如果要生成【m,n】之间的随机整数('整数切记要加1'):
     int temp = (int) m + (Math.random() * (n+1-m));

🎽实例

public class MathRandomTest {
    public static void main(String[] args) {
        //测试Math.random()方法
        //表示循环次数
        int end = 10;

        //生成[0,1)之间的随机数
        for (int i = 0; i < end; i++) {
            double random = Math.random();
            System.out.println(random);
        }

        System.out.println("------------我是一个分界线-------------");

        //生成[0,20)之间的随机数
        int bound01 =  20;
        for (int i = 0; i < end; i++) {
            double random = Math.random() * bound01;
            System.out.println(random);
        }

        System.out.println("------------我是一个分界线-------------");

        //生成[33,35]之间的随机数(闭区间)
        int leftBound =  33;
        int rightBound = 35;
        for (int i = 0; i < end; i++) {
            double random = leftBound + (Math.random() * (rightBound  - leftBound));
            System.out.println(random);
        }

        System.out.println("------------我是一个分界线-------------");

        //生成[33,35]之间的随机整数(加1)
        for (int i = 0; i < end; i++) {
            int random = (int) (leftBound + (Math.random() * (rightBound + 1  - leftBound)));
            System.out.println(random);
        }

    }
}

🐳运行截图

image-20220312101157720

image-20220312101305174

🏓3、currentTimeMillis类

java.lang包下System类中的静态内置方法 currentTimeMillis();
    
/**
 * @Author jinhuan
 * @Date 2022/3/12
 * 以毫秒为单位返回当前时间。
 * 请注意,虽然返回值的时间单位是毫秒,但值的粒度取决于底层操作系统,并且可能更大。
 * 例如,许多操作系统以几十毫秒为单位测量时间。
 * <p> 请参阅类<code>Date<code> 的描述,讨论“计算机时间”和协调世界时(UTC) 之间可能出现的细微差异。
 * @return 当前时间与 UTC 1970 年 1 月 1 日午夜之间的差异,以毫秒为单位。
 * @see java.util.Date
 */
public static native long currentTimeMillis();

简单来说就是:
    返回当前的计算机时间与GMT(格林威治)时间19700101000000秒的'时间差'
    //但是格林威治时间是标准时间  我们中国是以北京时间为标准时间 北京是东八区,与格林威治的时间差8个小时
    也就是说我们的"GMT"时间是 时间197011日08时0000秒
    
一般来说,我们都是用这个时间戳当做一个不会重复的随机数,然后进行操作(例如对某个数取模将其控制到一定范围)来作为随机数
Random中的无参构造都是采用这个方法来获取时间戳当做初始种子的    

🎯实例

public class CurrentTimeTest {
    public static void main(String[] args) {
        //获取当前时间
        long nowTime = System.currentTimeMillis();
        System.out.println("该时间戳的值是-->"+nowTime);
        //模运算获取随机数(这种方式不常用,因为计算机运算速度很快,示例代码太短,一毫秒足以运行结束,只是告诉一个简单的做法)
        int random01 = (int) (System.currentTimeMillis() % 100);
        System.out.println("random01的值是-->"+random01);

        int random02 = (int) (System.currentTimeMillis() % 10);
        System.out.println("random02的值是-->"+random02);

    }
}

🧣运行截屏

image-20220312110307412

🤡写在最后

有关java实现随机数的讲解就到这里了,其实随着我们的学习就会发现,关于随机数的运用在很多项目中都会使用到,希望大家看了之后还是能够手动实现一次来加深印象。文末附上了笔记下载链接。另外,我自己整理了一些自资源(笔记、书籍、软件等)分享在我的公众号上,非常欢迎大家来访白嫖和博主做朋友,一起学习进步!最后别忘啦支持一下博主哦,求三连!❤️❤️❤️

image-20220428105519763