這些Java中的隨機數生成工具

0.導言

本文主要是介紹在Java中生成隨機數的不同選擇和方式。實際應用中根據自己的需要選擇。

這些Java中的隨機數生成工具/類,總有一款適合你


1.Java API

在Java本身自帶的API中,為我們提供了幾種方式來獲得隨機數。我們來看下。

1.1. java.lang.Math

Math類的random方法將返回一個範圍為0.0(包括0.0)到1.0(不包括1.0)的雙精度值。看看該如何使用它來獲得一個在給定的範圍(最小和最大值間)內定義的隨機數:

<code>int randomWithMathRandom = (int) ((Math.random() * (max - min)) + min);/<code>

這行代碼的意思為為,我們用兩個整數,表示結果的隨機數的取值範圍在min和max之間。直接在JShell中簡要演示這個實現,我這裡參考如下(每次的結果可能都不同):


這些Java中的隨機數生成工具/類,總有一款適合你

1.2. java.util.Random

在Java 1.7之前,最流行的生成隨機數的方法是使用nextInt。有兩種途徑使用使用這個方法,即帶參數和不帶參數。無參數調用以近似相等的概率返回任何int值。所以很有可能得到負數,參考代碼如下:

<code>Random random = new Random();/<code>
<code>int randomWithNextInt = random.nextInt();/<code>

我在本機JShell中運行結果如下:


這些Java中的隨機數生成工具/類,總有一款適合你

如果使用綁定參數的netxInt方法(參數對返回值進行範圍約定了),我們將得到一個範圍內的數字,示例如下:

<code>int aVal = random(ival) ;/<code>

注意:這類需要主要,ival值必須是大於0,返回值在0和ival之間,但不包含ival;若參數小於等於0,則會報錯: java.lang.IllegalArgumentException.

演示:那麼要想得到一個在min和max之間的整數,我在JShell中演示結果如下:


這些Java中的隨機數生成工具/類,總有一款適合你

Java 8引入了新的ints方法,此方法返回java.util.stream.IntStream。IntStream,LongStream,DoubleStream等用於操作流中的數據,同時提供了相應的靜態方法來初始化它們自己。讓我們看看如何使用它們。

沒有參數的ints方法返回一個無限的int流,其代碼示例如下:

<code>IntStream unlimitedIntStream = random.ints();/<code>

也可以傳入一個參數限制流大小,示例如下:

<code>IntStream limitedIntStream = random.ints(streamSize);/<code>

當然,我們可以設置最大和最小值來生成帶範圍的int流,示例如下:

<code>IntStream limitedIntStreamWithinARange = random.ints(streamSize, min, max);/<code>

具體用戶可以查看Java API參考。

1.3. java.util.concurrent.ThreadLocalRandom

Java 1.7之後,為我們帶來了一種通過ThreadLocalRandom類來生成隨機數的更高效的新方法。這個類與隨機類有三個重要區別:

  • ü 不需要顯式地初始化ThreadLocalRandom的新實例。這有助於避免創建大量無用實例和浪費垃圾收集器時間的錯誤;
  • ü 不能為ThreadLocalRandom設置種子,這會導致一個實際的問題。如果我們需要設置種子,那麼我們應該避免使用這種產生隨機數的方式;
  • ü Random (隨機)類在多線程環境中表現不佳。

下面看看其工作方式:

<code>int randomWithThreadLocalRandomInARange = ThreadLocalRandom.current().nextInt(min, max);/<code>

使用Java 8或更高版本,我們就有了新的可能性。

首先,nextInt方法有兩種變體:

<code>int randomWithThreadLocalRandom = ThreadLocalRandom.current().nextInt();/<code>
<code>int randomWithThreadLocalRandomFromZero = ThreadLocalRandom.current().nextInt(max);/<code>

其次,更重要的是,我們可以使用ints方法:

<code>IntStream streamWithThreadLocalRandom = ThreadLocalRandom.current().ints();/<code>

1.4. java.util.SplittableRandom

Java 8還給我們帶來了一個非常快的生成器——SplittableRandom類。

正如我們在JavaDoc中看到的,這是一個用於並行計算的生成器。重要的是要知道實例不是線程安全的。所以,我們在使用這個類時必須小心。

還提供了nextInt和ints方法。使用nextInt,我們可以直接使用兩個參數設置最高最低範圍來調用:

<code>SplittableRandom splittableRandom = new SplittableRandom();/<code>
<code>int randomWithSplittableRandom = splittableRandom.nextInt(min, max);/<code>

這種方法可以檢查max參數是否大於min,否則會得到一個IllegalArgumentException。但是,它不能檢查我們是用正數還是負數。所以,參數都可以是任何負的。此外,我們還提供了一參和零參的調用。它們的工作方式和我們之前描述的一樣。

也有ints方法。這意味著我們可以很容易地獲得一個int流。必須清楚,使用中可以選擇一個有限的或無限的流。對於一個有限的流,我們可以設置最高最低的數字生成範圍約束:

<code>IntStream limitedIntStreamWithinARangeWithSplittableRandom = splittableRandom.ints(streamSize, min, max);/<code>

1. .5. java.security.SecureRandom

如果我們有安全敏感的應用程序,或說安全要求高的,推薦考慮使用SecureRandom。這是一個加密的強生成器。默認構造的實例不使用加密隨機種子。所以,我們應該:

  • ü 設置種子-但種子將是不可預測的;
  • ü 設置java.util.secureRandomSeed系統屬性為true;

這個類繼承自java.util.Random。因此,我們可以使用上面看到的所有方法。例如,如果我們需要獲取任何int值,那麼可調用沒有參數的nextInt:

<code>SecureRandom secureRandom = new SecureRandom();/<code>
<code>int randomWithSecureRandom = secureRandom.nextInt();/<code>

另一方面,如果我們需要設置範圍,我們可以調用帶參數的方法:

<code>int randomWithSecureRandomWithinARange = secureRandom.nextInt(max - min) + min;/<code>

必須當心:如果參數不大於0,這種使用方法會拋出IllegalArgumentException。

2.第三方API

正如我們所看到的,Java為我們提供了許多生成隨機數的類和方法。然而,還有第三方提供的API服務於此目的。我們來看看其中的一些。

2.1. org.apache.commons.math3.random.RandomDataGenerator

在Apache commons項目的commons數學庫中有很多生成器。最簡單,也可能最有用的就是RandomDataGenerator。它使用Well19937c(https://en.wikipedia.org/wiki/Well_equidistributed_long-period_linear)算法進行隨機生成。但是,我們可以提供我們的算法實現。

讓我們看看如何使用它。首先,我們必須添加依賴:

<dependency>

<groupid>org.apache.commons/<groupid>

<artifactid>commons-math3/<artifactid>

<version>3.6.1/<version>

可以在Maven Central上找到commons-math3的最新版本。

導入項目後,就可以開始使用它們工作了,示例如下:

<code>RandomDataGenerator randomDataGenerator = new RandomDataGenerator();/<code>
<code>int randomWithRandomDataGenerator = randomDataGenerator.nextInt(min, max);/<code>

2.2. it.unimi.dsi.util.XoRoShiRo128PlusRandom

這是最快的隨機數生成器實現之一。它是由米蘭大學信息科學系開發的。

該庫也可以在Maven中央存儲庫中使用。因此,讓引用時可以如下添加依賴:

<dependency>

<groupid>it.unimi.dsi/<groupid>

<artifactid>dsiutils/<artifactid>

<version>2.6.0/<version>

這個生成器繼承自java.util.Random。但是,如果我們看一下JavaDoc,就會發現只有一種方法可以使用它——nextInt方法。最重要的是,此方法僅可用於零參數和單參數調用。其他任何調用都將直接使用java.util.Random隨機方法。

例如,如想要得到一個範圍內的隨機數,你可以這樣寫:

<code>XoRoShiRo128PlusRandom xoroRandom = new XoRoShiRo128PlusRandom();/<code>
<code>int randomWithXoRoShiRo128PlusRandom = xoroRandom.nextInt(max - min) + min;/<code>

3.最後

通過本文,我們知道了有幾種實現隨機數生成的方法。然而,沒有最好的方法。因此,我們應該選擇最適合我們需要的。

你還知道有哪些有趣的隨機數生成類,分享一下吧.


分享到:


相關文章: