Java 生成随机数的 N 种方法
(給ImportNew加星標(biāo),提高Java技能)
編譯:ImportNew/覃佑樺
www.baeldung.com/java-generating-random-numbers
1.引言
本文將探討用 Java 生成隨機(jī)數(shù)的不同方法。
2.Java API
Java API 提供了幾種隨機(jī)數(shù)生成方法。讓我們一起來了解一下。
2.1.java.lang.Math
Math 類中的 random 方法返回一個 [0.0, 1.0) 區(qū)間的 double 值。下面這段代碼能得到一個 min 和 max 之間的隨機(jī)數(shù):
int randomWithMathRandom = (int) ((Math.random() * (max - min)) + min);2.2.java.util.Random
Java 1.7 之前,最流行的隨機(jī)數(shù)生成方法是 nextInt。這個方法提供了帶參數(shù)和無參數(shù)兩個版本。不帶參數(shù)調(diào)用時,nextInt 會以近似相等概率返回任意 int 值,因此很可能會得到負(fù)數(shù):
Random random = new Random(); int randomWithNextInt = random.nextInt();如果調(diào)用 netxInt 時帶上 bound 參數(shù),將得到預(yù)期區(qū)間內(nèi)的隨機(jī)數(shù):
int randomWintNextIntWithinARange = random.nextInt(max - min) + min;上面的代碼段能得到一個 [0, bound) 范圍內(nèi)的隨機(jī)數(shù)。因此 bound 參數(shù)必須大于0。否則會拋出 java.lang.IllegalArgumentException 異常。
Java 8 引入了新的 ints 方法,返回一個java.util.stream.IntStream,讓我們看看如何使用。
不帶參數(shù)的 ints方法將返回一個無限 int 流:
IntStream unlimitedIntStream = random.ints();調(diào)用時還可以指定參數(shù)來限制流大小:
當(dāng)然,也可以為生成數(shù)值設(shè)置最大值和最小值:
IntStream limitedIntStreamWithinARange = random.ints(streamSize, min, max);2.3.java.util.concurrent.ThreadLocalRandom
Java 1.7 中ThreadLocalRandom類提供了一種新的更高效的隨機(jī)數(shù)生成方法。與 Random 類相比有三個重要區(qū)別:
無需顯式初始化 ThreadLocalRandom 實例。這樣可以避免創(chuàng)建大量無用的實例,浪費垃圾收集器回收時間。
不能為 ThreadLocalRandom 設(shè)置隨機(jī)種子(seed),這可能會導(dǎo)致問題。如果需要設(shè)置隨機(jī)種子,應(yīng)該避免采用這種方式生成隨機(jī)數(shù)。
Random 類在多線程時表現(xiàn)不佳。
下面讓我們看看如何使用:
int randomWithThreadLocalRandomInARange = ThreadLocalRandom.current().nextInt(min, max);Java 8 及更高版本提供了幾種新方法。首先,nextInt 方法有兩個變體:
int randomWithThreadLocalRandom = ThreadLocalRandom.current().nextInt(); int randomWithThreadLocalRandomFromZero = ThreadLocalRandom.current().nextInt(max);其次,還可以使用 ints 方法:
IntStream streamWithThreadLocalRandom = ThreadLocalRandom.current().ints();2.4.java.util.SplittableRandom
Java 8 還帶來了一個快速隨機(jī)數(shù)生成器SplittableRandom類。
正如 JavaDoc 中描述的那樣,這是一個支持并行計算的隨機(jī)數(shù)生成器。值得注意的是,這個實例非線程安全。使用該類時需要當(dāng)心。
現(xiàn)在有了 nextInt 和 ints 方法。調(diào)用 nextInt 時,可以通過參數(shù)指定 top 和 bottom 范圍:
SplittableRandom splittableRandom = new SplittableRandom(); int randomWithSplittableRandom = splittableRandom.nextInt(min, max);這樣可以檢查 max 參數(shù)是否大于 min。檢查失敗會收到一個到IllegalArgumentException。但是,這里不會進(jìn)行正數(shù)或負(fù)數(shù)檢查。因此,參數(shù)可以填寫負(fù)數(shù)。也可以在調(diào)用時使用一個參數(shù)或者不使用參數(shù)。工作方式與之前描述的相同。
這里也提供了ints方法。這意味著可以輕松得到 int流。可以選擇流數(shù)據(jù)個數(shù)有限或無限。對于有限流,可以為數(shù)字生成范圍設(shè)置 top 和 bottom:
IntStream limitedIntStreamWithinARangeWithSplittableRandom = splittableRandom.ints(streamSize, min, max);2.5.java.security.SecureRandom
如果應(yīng)用程序?qū)Π踩舾?#xff0c;則應(yīng)考慮使用SecureRandom。這是一個強(qiáng)加密隨機(jī)數(shù)生成器。實例默認(rèn)構(gòu)造函數(shù)不使用隨機(jī)種子。因此,我們應(yīng)該:
設(shè)置隨機(jī)種子:隨機(jī)種子不可預(yù)測
設(shè)置 java.util.secureRandomSeed 系統(tǒng)屬性為 true。
該類繼承自java.util.Random。現(xiàn)在,我們介紹了上面各種隨機(jī)數(shù)生成方法。例如,如果需要獲取任意 int 值,調(diào)用 nextInt 時可以不帶參數(shù):
SecureRandom secureRandom = new SecureRandom(); int randomWithSecureRandom = secureRandom.nextInt();如果需要設(shè)置隨機(jī)數(shù)生成范圍,則可以在調(diào)用時帶 bound 參數(shù):
int randomWithSecureRandomWithinARange = secureRandom.nextInt(max - min) + min;切記,如果參數(shù)小于零會拋出 IllegalArgumentException。
3.第三方 API
上文的介紹中,Java 提供了許多隨機(jī)數(shù)生成類和方法。然而,也有很多第三方 API 可以生成隨機(jī)數(shù)。
下面對其中的一些進(jìn)行介紹。
3.1.org.apache.commons.math3.random.RandomDataGenerator
Apache Commons 項目中 Commons 數(shù)學(xué)庫提供了很多生成器。最簡單,也可能最有用的是 RandomDataGenerator。它使用 Well19937c 算法生成隨機(jī)數(shù)。我們也可以自行提供隨機(jī)數(shù)算法。
讓我們看看如何使用。首先,添加依賴項:
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-math3</artifactId><version>3.6.1</version> </dependency>最新版本的 commons-math3 可以在 Maven Central 中找到。
然后開始使用:
RandomDataGenerator randomDataGenerator = new RandomDataGenerator(); int randomWithRandomDataGenerator = randomDataGenerator.nextInt(min, max);3.2.it.unimi.dsi.util.XoRoShiRo128PlusRandom
這是最快的隨機(jī)數(shù)生成器之一。由米蘭大學(xué)信息科學(xué)系開發(fā)。
也可以在 Maven Central 倉庫中找到。首先,添加依賴項:
<dependency><groupId>it.unimi.dsi</groupId><artifactId>dsiutils</artifactId><version>2.6.0</version> </dependency>該生成器繼承了 java.util.Random 類。但是,如果仔細(xì)看一下 JavaDoc,就會發(fā)現(xiàn)只有一種調(diào)用方法——通過 nextInt 生成隨機(jī)數(shù)。最重要的是,該方法只提供無參和單個參數(shù)兩種版本。其他任何調(diào)用都將直接調(diào)用 java.util.Random 方法。
例如,如果想得到某個范圍內(nèi)的隨機(jī)數(shù),可以這樣寫:
XoRoShiRo128PlusRandom xoroRandom = new XoRoShiRo128PlusRandom(); int randomWithXoRoShiRo128PlusRandom = xoroRandom.nextInt(max - min) + min;4.總結(jié)
生成隨機(jī)數(shù)有很多辦法,但沒有最佳方法。因此,應(yīng)當(dāng)根據(jù)需求選擇最合適的方法。
本文的完整示例可以在? GitHub ?上下載。
github.com/eugenp/tutorials/tree/master/java-numbers-3
有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)
歡迎大家關(guān)注Java之道公眾號
好文章,我在看??
總結(jié)
以上是生活随笔為你收集整理的Java 生成随机数的 N 种方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NYOJ 643 发短信 暴力求解
- 下一篇: 一个命令,让你的网站支持https