专业的JAVA编程教程与资源

网站首页 > java教程 正文

Java修炼终极指南:31. 创建伪随机数生成器的流

temp10 2024-09-08 09:29:11 java教程 10 ℃ 0 评论


在创建伪随机数生成器的流之前,让我们先创建一个伪随机数的流。首先,让我们看看如何使用传统的Random、SecureRandom和ThreadLocalRandom来实现。由于这三个伪随机数生成器包含了如ints()返回IntStream、doubles()返回DoubleStream等方法,我们可以很容易地生成一个(无)限的伪随机数流,如下所示:

Java修炼终极指南:31. 创建伪随机数生成器的流

Random rnd = new Random();  
// ints() 方法返回一个无限流  
int[] arrOfInts = rnd.ints(10).toArray(); // 10个整数的流  
// 或者,简写为  
int[] arrOfInts = new Random().ints(10).toArray();


在我们的例子中,我们将生成的伪随机数收集到一个数组中。当然,你可以按自己的需求处理它们。我们可以通过SecureRandom获得类似的结果,如下所示:

SecureRandom secureRnd = SecureRandom.getInstanceStrong();  
int[] arrOfSecInts = secureRnd.ints(10).toArray();  
// 或者,简写为  
int[] arrOfSecInts = SecureRandom.getInstanceStrong().ints(10).toArray();


那么ThreadLocalRandom呢?这里有一个例子:

ThreadLocalRandom tlRnd = ThreadLocalRandom.current();  
int[] arrOfTlInts = tlRnd.ints(10).toArray();  
// 或者,简写为  
int[] arrOfTlInts = ThreadLocalRandom.current().ints(10).toArray();


如果你只需要一个0.0到1.0之间的double数流,那么可以依赖Math.random(),它内部使用了java.util.Random的一个实例。以下示例收集了一个0.0到0.5之间的double数数组。当生成第一个大于0.5的double数时,流将停止:

Supplier<Double> doubles = Math::random;  
double[] arrOfDoubles = Stream.generate(doubles)                      
    .takeWhile(t -> t < 0.5d)  
    .mapToDouble(i -> i)  
    .toArray();


那么如何使用新的JDK 17 API呢?RandomGenerator包含了众所周知的ints()、doubles()等方法,这些方法在其所有子接口中都是可用的。例如,StreamableGenerator可以这样使用:

StreamableGenerator streamableRnd   
   = StreamableGenerator.of("L128X1024MixRandom");  
int[] arrOfStRndInts = streamableRnd.ints(10).toArray();  
// 或者,简写为  
StreamableGenerator.of("L128X1024MixRandom").ints(10).toArray();


以同样的方式,我们可以使用JumpableGenerator、LeapableGenerator等。好的,现在让我们回到我们的问题上。如何生成伪随机数生成器的流?RandomGenerator的所有子接口都包含一个名为rngs()的方法,它有多种形式。不带参数时,此方法返回一个实现RandomGenerator接口的新伪随机数生成器的无限流。以下代码生成了5个StreamableGenerator实例,每个实例生成了10个伪随机整数:

StreamableGenerator streamableRnd   
   = StreamableGenerator.of("L128X1024MixRandom");  
List<int[]> listOfArrOfIntsSG   
   = streamableRnd.rngs(5) // 获取5个伪随机数生成器  
     .map(r -> r.ints(10)) // 每个生成器生成10个整数  
     .map(r -> r.toArray())  
     .collect(Collectors.toList());


我们可以使用JumpableGenerator完成同样的事情,但可能更喜欢使用jumps(),它实现了这种类型生成器的特定行为:

JumpableGenerator jumpableRnd   
   = JumpableGenerator.of("Xoshiro256PlusPlus");  
List<int[]> listOfArrOfIntsJG = jumpableRnd.jumps(5)                    
   .map(r -> {  
        JumpableGenerator jg = (JumpableGenerator) r;  
        int[] ints = new int[10];  
        for (int i = 0; i < 10; i++) {  
           ints[i] = jg.nextInt();  
           jg.jump();  
        }  
        return ints;  
   })  
   .collect(Collectors.toList());


同样的事情可以通过LeapableGenerator实现。这次,我们可以使用rngs(),或者使用leaps(),它实现了这种类型生成器的特定行为:

LeapableGenerator leapableRnd   
   = LeapableGenerator.of("Xoshiro256PlusPlus");  
List<int[]> listOfArrOfIntsLG = leapableRnd.leaps(5)                     
   .map(r -> {  
        LeapableGenerator lg = (LeapableGenerator) r;  
        int[] ints = new int[10];  
        for (int i = 0; i < 10; i++) {  
           ints[i] = lg.nextInt();  
           lg.leap();  
        }  
        return ints;  
   })  
   .collect(Collectors.toList());


接下来,让我们看看如何交错使用传统和新的伪随机数生成器。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表