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ó.