package com.ydlclass.random;

import java.util.Arrays;
import java.util.Random;
import java.util.function.IntConsumer;

public class RandomTest {
    public static void main(String[] args) {
        //这个类的使用相比于math.random的功能多
        //random这个类存在两种构造器,其中一种为空参构造器,另外一种构造器时有参构造器,有参构造器中传入的其实一个种子
        //当种子值相同时,两次生成的随机数其实就是相同的;
        //@@@**!!其实这两种构造器的本质实际上都产生了种子值,只是前一种无参构造器使用的时间戳异或生成的种子值;有参构造只不过
        //可以给我们一个自己填写种子值的机会

        Random random = new Random();
        int i = random.nextInt();
        System.out.println(i);//这种方式时在整数类型的范围内生成了一个新的随机数

        int i1 = random.nextInt(10);//生成的随机数为0—10以内的一个随机整数,也就是将随机书的范围缩小了
        System.out.println(i1);
        boolean b = random.nextBoolean();//随机生成一个布尔值
        double v = random.nextGaussian();//随机生成一个符合正态分布的一个值(即生成的大部分的数字时在正中间的,两端的比较少)
        byte[] bytes = new byte[12];
        random.nextBytes(bytes);//随机生成的byte数组并且将这些数字存放在一个byte数组之中

        //箭头函数,也就是匿名内部类,再次复习匿名内部类额地方内容
        System.out.println("箭头函数式的生成5个随机数:");
        random.ints(5).forEach(item->{//生成5个随机的int值,并且使用了foreach函数,并且这个函数中使用了一个匿名内部类
            //只不过使用了一个箭头函数来写


            //解释:random这个类的实例方法ints(),可以传入一个长度,这个长度可以是long类型,用来规定这个流的长度,并且返回了一个长度为5的int类型的流;
            //:random.ints(5)规定长度为5,且为一个流;由于此时返回值为一个流,我们可以使用这个流调用forEach()函数;
            //forEach()函数可以为调用此方法的流中的每个对象执行同一个动作;并且forEach()函数中的参数是一个函数式接口,通过ctrl+鼠标左键,可以知道这个函数式接口是:IntCustomer,即int消费者
            //由于这个接口函数式接口,那么我们可以使用匿名内部类的方式实现参数的传递

            System.out.println(item);
        });


        System.out.println("匿名内部类的方式实现五个随机数的打印:");

        random.ints(5).forEach(new IntConsumer() {
            @Override
            public void accept(int value) {
                System.out.println(value);//这里将流中的每个值,执行了同一个动作,并且这个动作就是单纯的打印
                //由于这个匿名内部类实现的是一个接口,所以它需要实现这个接口中的每个抽象函数,并且,匿名内部类的实现
                //可以将new,函数式接口名,括号,都直接省略,以及这个接口的函数名,权限修饰符,以及,参数的类型全都省略,
                //保留{},以及方法体中的内容,直接以一种简写的方式实现这个对象的传递,(当方法体中只含有一个return语句时,我们可以将{}都省略,甚至省略return)
                //即实现了函数式接口的一个操作。
            }
        });

        System.out.println("函数式接口的编写方式实现二:");
        random.ints(5).forEach(element-> System.out.println(element));//直接将花括号同时省略掉
        


        System.out.println(Arrays.toString(bytes));//

        System.out.println(v);


        System.out.println("不含有种子值的一个Random");
        for (int i2 = 0; i2 < 5; i2++) {
            Random random1 = new Random();//每次循环生成一个Random类,这个类中是没有一个种子值的
            for (int j = 0; j < 5; j++) {
                System.out.print(" " + random1.nextInt(10) + ", ");

            }
            System.out.println("");

        }

        System.out.println("含有种子值的一个Random");
        for (int j = 0; j < 5; j++) {
            Random random2 = new Random(100);//这个循环之中的random每次生成的Random类的种子值是固定的,并且一定要确保random这个类一定
            //需要在每次循环中创建一次才可以
            for (int k = 0; k < 5; k++) {
                System.out.print(" " + random2.nextInt(10) + ", ");
            }
            System.out.println("");

        }

        //可以很清楚的发现,第二种含有种子值,且种子值固定的,这个random,只要种子值相同,那么这些random每次生成的随机数都是相同的

        //这种随机数的生成可以用于一定的测试数据的生成


    }
}