Generovanie náhodných čísel v Jave

1. Prehľad

V tomto tutoriáli preskúmame rôzne spôsoby generovania náhodných čísel v Jave.

2. Používanie Java API

Java API nám poskytuje niekoľko spôsobov, ako dosiahnuť náš účel. Pozrime sa na niektoré z nich.

2.1. java.lang.Math

The náhodný metóda Matematika trieda vráti a dvojitý hodnotu v rozsahu od 0,0 (vrátane) do 1,0 (bez). Pozrime sa, ako by sme ho použili na získanie náhodného čísla v danom rozsahu definovanom ako min a max:

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

2.2. java.util.Random

Pred programom Java 1.7 sa používal najpopulárnejší spôsob generovania náhodných čísel nextInt. Existujú dva spôsoby použitia tejto metódy, s parametrami a bez nich. Vyvolanie bez parametra vráti ľubovoľný z parametrov int hodnoty s približne rovnakou pravdepodobnosťou. Je teda veľmi pravdepodobné, že dostaneme záporné čísla:

Random random = nový Random (); int randomWithNextInt = random.nextInt ();

Ak použijeme netxInt vyvolanie s viazaný parameter dostaneme čísla v rozsahu:

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

Takto získate číslo medzi 0 (vrátane) a parametrom (výhradné). Takže viazaný parameter musí byť väčší ako 0. V opačnom prípade dostaneme a java.lang.IllegalArgumentException.

Java 8 predstavila nové ints metódy, ktoré vracajú a java.util.stream.IntStream. Pozrime sa, ako ich používať.

The ints metóda bez parametrov vracia neobmedzený prúd int hodnoty:

IntStream unlimitedIntStream = random.ints ();

Môžeme tiež vložiť jeden parameter na obmedzenie veľkosti streamu:

IntStream limitedIntStream = random.ints (streamSize);

A samozrejme môžeme nastaviť maximum a minimum pre vygenerovaný rozsah:

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

2.3. java.util.concurrent.ThreadLocalRandom

Vydanie Java 1.7 nám prinieslo nový a efektívnejší spôsob generovania náhodných čísel cez internet ThreadLocalRandom trieda. Tento má tri dôležité rozdiely od Náhodné trieda:

  • Nemusíme výslovne inicializovať novú inštanciu ThreadLocalRandom. To nám pomáha vyhnúť sa chybám pri vytváraní množstva zbytočných prípadov a plytvaní časom pre zberačov odpadu
  • Semeno nemôžeme nastaviť ThreadLocalRandom, čo môže viesť k skutočnému problému. Ak potrebujeme nastaviť semeno, mali by sme sa vyhnúť tomuto spôsobu generovania náhodných čísel
  • Náhodné trieda nepodáva dobrý výkon v prostredí s viacerými vláknami

Teraz sa pozrime, ako to funguje:

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

S programom Java 8 alebo novším máme nové možnosti. Po prvé, máme dve varianty pre nextInt metóda:

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

Po druhé, a čo je dôležitejšie, môžeme použiť ints metóda:

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

2.4. java.util.SplittableRandom

Java 8 nám tiež priniesla skutočne rýchly generátor - SplittableRandom trieda.

Ako vidíme v JavaDoc, jedná sa o generátor na použitie v paralelných výpočtoch. Je dôležité vedieť, že inštancie nie sú bezpečné z hľadiska vlákien. Pri používaní tejto triedy teda musíme byť opatrní.

Máme k dispozícii nextInt a ints metódy. S nextInt môžeme priamo nastaviť horný a dolný rozsah pomocou vyvolania dvoch parametrov:

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

Tento spôsob používania kontroluje, či max parameter je väčší ako min. V opačnom prípade dostaneme IllegalArgumentException. Nekontroluje však, či pracujeme s kladnými alebo zápornými číslami. Ktorýkoľvek z parametrov môže byť teda záporný. K dispozícii máme tiež vyvolanie jedného a nulového parametra. Fungujú rovnako, ako sme už opísali.

Máme k dispozícii ints metódy tiež. To znamená, že môžeme ľahko získať prúd int hodnoty. Na objasnenie si môžeme zvoliť obmedzený alebo neobmedzený stream. Pre obmedzený stream môžeme nastaviť hornú a dolnú časť rozsahu generovania čísel:

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

2.5. java.security.SecureRandom

Ak máme aplikácie citlivé na bezpečnosť, mali by sme zvážiť použitie SecureRandom. Toto je kryptograficky silný generátor. Predvolene zostavené inštancie nepoužívajú kryptograficky náhodné semená. Mali by sme buď:

  • Nastavte semeno - v dôsledku toho bude semeno nepredvídateľné
  • Nastaviť java.util.secureRandomSeed systémový majetok do pravda

Táto trieda dedí z java.util.Random. Takže máme k dispozícii všetky metódy, ktoré sme videli vyššie. Napríklad, ak potrebujeme získať čokoľvek z int hodnoty, potom zavoláme nextInt bez parametrov:

SecureRandom secureRandom = nový SecureRandom (); int randomWithSecureRandom = secureRandom.nextInt ();

Na druhej strane, ak potrebujeme nastaviť rozsah, môžeme to nazvať pomocou viazaný parameter:

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

Musíme si uvedomiť, že tento spôsob použitia to hodí IllegalArgumentException ak parameter nie je väčší ako nula.

3. Používanie rozhraní API tretích strán

Ako sme videli, Java nám poskytuje množstvo tried a metód na generovanie náhodných čísel. Na tento účel však existujú aj API tretích strán.

Ideme sa pozrieť na niektoré z nich.

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

V knižnici commons matematiky je veľa generátorov z projektu Apache Commons. Najjednoduchší a pravdepodobne najužitočnejší je RandomDataGenerator. Používa No19937c algoritmus pre náhodné generovanie. Môžeme však poskytnúť implementáciu nášho algoritmu.

Pozrime sa, ako to využiť. Najprv musíme pridať závislosť:

 org.apache.commons commons-math3 3.6.1 

Najnovšia verzia servera commons-math3 nájdete na Maven Central.

Potom s tým môžeme začať pracovať:

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

3.2. it.unimi.dsi.util.XoRoShiRo128PlusRandom

Toto je určite jedna z najrýchlejších implementácií generátora náhodných čísel. Bol vyvinutý na Katedre informačných vied na Milánskej univerzite.

Knižnica je k dispozícii aj v archívoch Maven Central. Pridajme teda závislosť:

 it.unimi.dsi dsiutils 2.6.0 

Tento generátor dedí z java.util.Random. Ak sa však pozrieme na JavaDoc, uvedomíme si, že existuje iba jeden spôsob jeho použitia - prostredníctvom nextInt metóda. Táto metóda je predovšetkým k dispozícii iba pri vyvolaní nulového a jedného parametra. Akékoľvek ďalšie vyvolanie bude priamo používať java.util.Random metódy.

Napríklad, ak chceme získať náhodné číslo v rozsahu, napíšeme:

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

4. Záver

Existuje niekoľko spôsobov, ako implementovať generovanie náhodných čísel. Neexistuje však najlepší spôsob. Preto by sme si mali zvoliť ten, ktorý najlepšie vyhovuje našim potrebám.

Celý príklad nájdete na GitHub.