Véletlen számok generálása Java-ban

1. Áttekintés

Ebben az oktatóanyagban megvizsgáljuk a véletlenszámok Java-ban történő előállításának különböző módjait.

2. Java API használata

A Java API többféleképpen nyújt számunkra célunk elérését. Lássunk néhányat közülük.

2.1. java.lang.Math

A véletlen módszere Math osztály visszatér a kettős érték a 0,0 (beleértve) és az 1,0 (kizárólagos) tartományban. Lássuk, hogyan használhatnánk véletlenszámot egy adott által meghatározott tartományban min és max:

int randomWithMathRandom = (int) ((Math.random () * (max - min)) + min);

2.2. java.util.Random

A Java 1.7 előtt a véletlenszámok előállításának legnépszerűbb módja a használat volt következőInt. Ennek a módszernek kétféle módja volt, paraméterekkel és azok nélkül. A paraméter nélküli hívás bármelyikét visszaadja int értékek közel azonos valószínűséggel. Tehát nagyon valószínű, hogy negatív számokat kapunk:

Véletlenszerű véletlenszerű = új Véletlenszerű (); int randomWithNextInt = random.nextInt ();

Ha a netxInt meghívás a összekötött paramétert, egy tartományon belüli számokat kapunk:

int randomWintNextIntWithinARange = random.nextInt (max - min) + min;

Ez 0 (beleértve) és paraméter (kizáró) közötti számot kap. Tehát a kötött paraméternek nagyobbnak kell lennie, mint 0. Ellenkező esetben kapunk egy java.lang.IllegalArgumentException.

A Java 8 bemutatta az újat ints módszerek, amelyek visszaadják a java.util.stream.IntStream. Lássuk, hogyan kell használni őket.

A ints paraméter nélküli metódus korlátlan int értékek:

IntStream unlimitedIntStream = random.ints ();

Átadhatunk egyetlen paramétert is a folyam méretének korlátozására:

IntStream limitedIntStream = random.ints (streamSize);

Természetesen beállíthatjuk a létrehozott tartomány maximális és minimális értékét:

IntStream limitedIntStreamWithinARange = random.ints (streamSize, min, max);

2.3. java.util.concurrent.ThreadLocalRandom

A Java 1.7 kiadás új és hatékonyabb módszert hozott a véletlenszámok előállítására a ThreadLocalRandom osztály. Ennek három fontos különbsége van a Véletlen osztály:

  • Nem kell kifejezetten új kezdeményezést indítanunk ThreadLocalRandom. Ez segít elkerülni a sok haszontalan példány létrehozásának hibáit és pazarolni a szemétgyűjtő időt
  • Nem tudjuk beállítani a magot ThreadLocalRandom, ami valódi problémához vezethet. Ha be kell állítanunk a magot, akkor kerülnünk kell a véletlenszámok előállításának ezt a módját
  • Véletlen osztály nem teljesít jól több szálas környezetben

Most nézzük meg, hogyan működik:

int randomWithThreadLocalRandomInARange = ThreadLocalRandom.current (). nextInt (min, max);

A Java 8 vagy újabb verzióval új lehetőségeink vannak. Először is két változatunk van a következőInt módszer:

int randomWithThreadLocalRandom = ThreadLocalRandom.current (). nextInt (); int randomWithThreadLocalRandomFromZero = ThreadLocalRandom.current (). nextInt (max);

Másodszor, és ami még fontosabb, használhatjuk a ints módszer:

IntStream streamWithThreadLocalRandom = ThreadLocalRandom.current (). Ints ();

2.4. java.util.SplittableRandom

A Java 8 egy igazán gyors generátort is hozott nekünk - a SplittableRandom osztály.

Amint a JavaDoc-ban láthatjuk, ez egy generátor párhuzamos számításokhoz. Fontos tudni, hogy a példányok nem biztonságosak a szálak számára. Tehát vigyáznunk kell ennek az osztálynak a használatakor.

Rendelkezünk a következőInt és ints mód. Val vel következőInt közvetlenül beállíthatjuk a felső és az alsó tartományt a két paraméterhívással:

SplittableRandom splittableRandom = új SplittableRandom (); int randomWithSplittableRandom = oszthatóRandom.nextInt (min, max);

A használat ilyen módja azt ellenőrzi, hogy a max paraméter nagyobb, mint min. Ellenkező esetben kapunk egy IllegalArgumentException. Nem ellenőrzi azonban, hogy pozitív vagy negatív számokkal dolgozunk-e. Tehát bármelyik paraméter negatív lehet. Rendelkezésre állnak egy- és nulla paraméteres invokációk is. Ezek ugyanúgy működnek, mint korábban leírtuk.

Rendelkezünk a ints módszerek is. Ez azt jelenti, hogy könnyedén megszerezhetjük az áramot int értékek. Hogy tisztázzuk, választhatunk korlátozott vagy korlátlan adatfolyamot. Korlátozott adatfolyam esetén beállíthatjuk a számgenerálási tartomány felső és alsó részét:

IntStream limitedIntStreamWithinARangeWithSplittableRandom = splittableRandom.ints (streamSize, min, max);

2.5. java.security.SecureRandom

Ha biztonsági szempontból érzékeny alkalmazásaink vannak, akkor fontolóra kell venni a használatát SecureRandom. Ez egy kriptográfiailag erős generátor. Az alapértelmezetten felépített példányok nem használnak kriptográfiailag véletlenszerű magokat. Tehát:

  • Állítsa be a magot - következésképpen a mag kiszámíthatatlan lesz
  • Állítsa be a java.util.secureRandomSeed rendszer tulajdonság a igaz

Ez az osztály örököl java.util.Random. Tehát rendelkezésünkre áll a fentiekben ismertetett összes módszer. Például, ha meg kell szereznünk a int értékeket, akkor felhívjuk következőInt paraméterek nélkül:

SecureRandom secureRandom = új SecureRandom (); int randomWithSecureRandom = secureRandom.nextInt ();

Másrészt, ha be kell állítanunk a tartományt, akkor a összekötött paraméter:

int randomWithSecureRandomWithinARange = secureRandom.nextInt (max - min) + min;

Emlékeznünk kell arra, hogy a használat ilyen módja dob IllegalArgumentException ha a paraméter nem nagyobb, mint nulla.

3. Harmadik fél API-k használata

Mint láttuk, a Java rengeteg osztályt és módszert biztosít számunkra a véletlenszámok előállításához. Vannak azonban harmadik féltől származó API-k is erre a célra.

Megnézzük néhányukat.

3.1. org.apache.commons.math3.random.RandomDataGenerator

Az Apache Commons projektből sok generátor található a commons matematikai könyvtárban. A legegyszerűbb és valószínűleg a leghasznosabb a RandomDataGenerator. Használja a Well19937c algoritmus a véletlenszerű generáláshoz. Azonban biztosíthatjuk algoritmusunk megvalósítását.

Lássuk, hogyan kell használni. Először hozzá kell adnunk a függőséget:

 org.apache.commons commons-math3 3.6.1 

A legfrissebb verziója commons-math3 megtalálható a Maven Central oldalon.

Akkor elkezdhetjük a munkát:

RandomDataGenerator randomDataGenerator = új RandomDataGenerator (); int randomWithRandomDataGenerator = randomDataGenerator.nextInt (min, max);

3.2. it.unimi.dsi.util.XoRoShiRo128PlusRandom

Természetesen ez az egyik leggyorsabb véletlenszám-generátor megvalósítás. A milánói egyetem Informatikai Tanszékén dolgozták ki.

A könyvtár a Maven Central adattáraiban is elérhető. Tehát tegyük hozzá a függőséget:

 it.unimi.dsi dsiutils 2.6.0 

Ez a generátor örököl java.util.Random. Ha azonban egy pillantást vetünk a JavaDoc-ra, rájövünk, hogy csak egyetlen módja van a használatának - a következőInt módszer. Ez a módszer mindenekelőtt csak a nulla és egy paraméteres invokációk esetén érhető el. A többi invokáció bármelyike ​​közvetlenül használja a java.util.Random mód.

Például, ha véletlenszerű számot akarunk kapni egy tartományon belül, akkor ezt írjuk:

XoRoShiRo128PlusRandom xoroRandom = új XoRoShiRo128PlusRandom (); int randomWithXoRoShiRo128PlusRandom = xoroRandom.nextInt (max - perc) + perc;

4. Következtetés

A véletlenszám-generálás megvalósításának számos módja van. Nincs azonban legjobb módszer. Következésképpen az igényeinknek leginkább megfelelőt kell választanunk.

A teljes példa a GitHub oldalon található.