Generiranje slučajnih brojeva u Javi

1. Pregled

U ovom uputstvu istražit ćemo različite načine generiranja slučajnih brojeva u Javi.

2. Korištenje Java API-ja

Java API pruža nam nekoliko načina da postignemo svoju svrhu. Pogledajmo neke od njih.

2.1. java.lang.Math

The slučajno metoda Matematika klasa će vratiti a dvostruko vrijednost u rasponu od 0,0 (uključujući) do 1,0 (isključujući). Pogledajmo kako bismo ga koristili za dobivanje slučajnog broja u zadanom rasponu definiranom pomoću min i maks:

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

2.2. java.util.Slučajno

Prije Jave 1.7, bio je najpopularniji način generiranja slučajnih brojeva nextInt. Dva su načina korištenja ove metode, sa i bez parametara. Poziv bez parametra vraća bilo koji od int vrijednosti s približno jednakom vjerojatnošću. Dakle, vrlo je vjerojatno da ćemo dobiti negativne brojeve:

Slučajni slučajni = novi Random (); int randomWithNextInt = random.nextInt ();

Ako koristimo netxInt zazivanje s vezani parametar, dobit ćemo brojeve u rasponu:

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

To će nam dati broj između 0 (uključujući) i parametar (isključivo). Dakle, vezani parametar mora biti veći od 0. Inače ćemo dobiti java.lang.IllegalArgumentException.

Java 8 predstavila je novo inti metode koje vraćaju a java.util.stream.IntStream. Pogledajmo kako ih koristiti.

The inti metoda bez parametara vraća neograničen tok int vrijednosti:

IntStream unlimitedIntStream = random.ints ();

Također možemo proslijediti jedan parametar da ograničimo veličinu streama:

IntStream limitedIntStream = random.ints (streamSize);

I, naravno, možemo postaviti maksimum i minimum za generirani raspon:

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

2.3. java.util.concurrent.ThreadLocalRandom

Izdanje Java 1.7 donijelo nam je novi i učinkovitiji način generiranja slučajnih brojeva putem ThreadLocalRandom razred. Ovaj ima tri važne razlike od Slučajno razred:

  • Ne trebamo izričito pokretati novu instancu ThreadLocalRandom. To nam pomaže da izbjegnemo pogreške stvaranja puno beskorisnih primjeraka i gubljenja vremena za skupljanje smeća
  • Ne možemo postaviti sjeme ThreadLocalRandom, što može dovesti do stvarnog problema. Ako trebamo postaviti sjeme, tada bismo trebali izbjegavati ovaj način generiranja slučajnih brojeva
  • Slučajno klasa ne izvodi se dobro u okruženjima s više niti

Pogledajmo sada kako to funkcionira:

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

S Javom 8 ili novijom imamo nove mogućnosti. Prvo, imamo dvije varijacije za nextInt metoda:

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

Drugo, i što je još važnije, možemo koristiti inti metoda:

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

2.4. java.util.SplittableRandom

Java 8 nam je donijela i vrlo brz generator - SplittableRandom razred.

Kao što možemo vidjeti u JavaDocu, ovo je generator za uporabu u paralelnim proračunima. Važno je znati da instance nisu zaštićene od niti. Dakle, moramo paziti kada koristimo ovu nastavu.

Dostupni smo nextInt i inti metode. S nextInt možemo izravno postaviti gornji i donji raspon pomoću poziva dva parametra:

SplittableRandom splittableRandom = novo SplittableRandom (); int randomWithSplittableRandom = splittableRandom.nextInt (min, max);

Ovaj način korištenja provjerava da li maks parametar je veći od min. Inače ćemo dobiti IlegalArgumentException. Međutim, ne provjerava radimo li s pozitivnim ili negativnim brojevima. Dakle, bilo koji od parametara može biti negativan. Također, imamo dostupne pozive s jednim i nula parametara. Oni djeluju na isti način kao što smo prije opisali.

Dostupni smo inti metode. To znači da možemo lako dobiti tok int vrijednosti. Da pojasnimo, možemo odabrati ograničeni ili neograničeni tok. Za ograničeni tok možemo postaviti vrh i dno za raspon generiranja broja:

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

2.5. java.security.SecureRandom

Ako imamo sigurnosno osjetljive aplikacije, trebali bismo razmotriti upotrebu SecureRandom. Ovo je kriptografski jak generator. Primjeri konstruirani prema zadanim postavkama ne koriste kriptografski nasumična sjemena. Dakle, trebali bismo ili:

  • Postavite sjeme - posljedično, sjeme će biti nepredvidljivo
  • Postavi java.util.secureRandomSeed svojstvo sustava na pravi

Ova klasa nasljeđuje od java.util.Slučajno. Dakle, imamo na raspolaganju sve metode koje smo vidjeli gore. Na primjer, ako trebamo dobiti bilo koji od int vrijednosti, tada ćemo nazvati nextInt bez parametara:

SecureRandom secureRandom = novi SecureRandom (); int randomWithSecureRandom = secureRandom.nextInt ();

S druge strane, ako moramo postaviti raspon, možemo ga nazvati s vezani parametar:

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

Moramo se sjetiti da ovaj način njegove upotrebe baca IlegalArgumentException ako parametar nije veći od nule.

3. Korištenje API-ja treće strane

Kao što smo vidjeli, Java nam nudi puno klasa i metoda za generiranje slučajnih brojeva. Međutim, u tu svrhu postoje i API-ji treće strane.

Pogledat ćemo neke od njih.

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

U biblioteci zajedničke matematike iz projekta Apache Commons postoji puno generatora. Najlakši i vjerojatno najkorisniji je RandomDataGenerator. Koristi Pa19937c algoritam za slučajnu generaciju. Međutim, možemo pružiti implementaciju našeg algoritma.

Pogledajmo kako ga koristiti. Prvo, moramo dodati ovisnost:

 org.apache.commons commons-math3 3.6.1 

Najnovija verzija commons-math3 možete pronaći na Maven Central.

Tada možemo početi raditi s tim:

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

3.2. it.unimi.dsi.util.XoRoShiRo128PlusRandom

Svakako, ovo je jedna od najbržih implementacija generatora slučajnih brojeva. Razvijen je na Odjelu za informacijske znanosti Sveučilišta u Milanu.

Biblioteka je također dostupna u spremištima Maven Central. Dakle, dodajmo ovisnost:

 it.unimi.dsi dsiutils 2.6.0 

Ovaj generator nasljeđuje od java.util.Slučajno. Međutim, ako bacimo pogled na JavaDoc, shvatit ćemo da postoji samo jedan način njegove upotrebe - putem nextInt metoda. Iznad svega, ova je metoda dostupna samo s pozivima s nula i jednim parametrom. Bilo koji drugi poziv će se izravno koristiti java.util.Slučajno metode.

Na primjer, ako želimo dobiti slučajni broj unutar raspona, napisali bismo:

XoRoShiRo128PlusRandom xoroRandom = novo XoRoShiRo128PlusRandom (); int randomWithXoRoShiRo128PlusRandom = xoroRandom.nextInt (max - min) + min;

4. Zaključak

Postoji nekoliko načina za primjenu generiranja slučajnih brojeva. Međutim, ne postoji najbolji način. Stoga bismo trebali odabrati onu koja najbolje odgovara našim potrebama.

Cjelovit primjer možete pronaći na GitHubu.