Willekeurige getallen genereren in Java

1. Overzicht

In deze zelfstudie onderzoeken we verschillende manieren om willekeurige getallen in Java te genereren.

2. Java API gebruiken

De Java API biedt ons verschillende manieren om ons doel te bereiken. Laten we er een paar bekijken.

2.1. java.lang.Math

De willekeurig methode van de Wiskunde klasse retourneert een dubbele waarde in een bereik van 0,0 (inclusief) tot 1,0 (exclusief). Laten we eens kijken hoe we het zouden gebruiken om een ​​willekeurig getal te krijgen in een bepaald bereik gedefinieerd door min en max. hoogte:

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

2.2. java.util.Random

Vóór Java 1.7 was het gebruik van volgendeInt. Er waren twee manieren om deze methode te gebruiken, met en zonder parameters. De no-parameter aanroep retourneert een van de int waarden met ongeveer gelijke waarschijnlijkheid. Het is dus zeer waarschijnlijk dat we negatieve getallen krijgen:

Random random = nieuw Random (); int randomWithNextInt = random.nextInt ();

Als we de netxInt aanroep met de gebonden parameter, we krijgen getallen binnen een bereik:

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

Dit geeft ons een getal tussen 0 (inclusief) en parameter (exclusief). De gebonden parameter moet dus groter zijn dan 0. Anders krijgen we een java.lang.IllegalArgumentException.

Java 8 introduceerde het nieuwe ints methoden die een java.util.stream.IntStream. Laten we eens kijken hoe we ze kunnen gebruiken.

De ints methode zonder parameters geeft een onbeperkte stroom van int waarden:

IntStream unlimitedIntStream = random.ints ();

We kunnen ook een enkele parameter doorgeven om de stream-grootte te beperken:

IntStream limitedIntStream = random.ints (streamSize);

En natuurlijk kunnen we het maximum en minimum instellen voor het gegenereerde bereik:

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

2.3. java.util.concurrent.ThreadLocalRandom

De release van Java 1.7 bracht ons een nieuwe en efficiëntere manier om willekeurige getallen te genereren via de ThreadLocalRandom klasse. Deze heeft drie belangrijke verschillen met de Willekeurig klasse:

  • We hoeven niet expliciet een nieuw exemplaar van ThreadLocalRandom. Dit helpt ons om fouten te voorkomen door veel nutteloze instanties te creëren en tijd te verspillen aan garbage collector
  • We kunnen het zaad niet instellen voor ThreadLocalRandom, wat tot een echt probleem kan leiden. Als we het zaad moeten instellen, moeten we deze manier van het genereren van willekeurige getallen vermijden
  • Willekeurig klasse presteert niet goed in omgevingen met meerdere threads

Laten we nu eens kijken hoe het werkt:

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

Met Java 8 of hoger hebben we nieuwe mogelijkheden. Ten eerste hebben we twee varianten voor de volgendeInt methode:

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

Ten tweede, en nog belangrijker, kunnen we de ints methode:

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

2.4. java.util.SplittableRandom

Java 8 heeft ons ook een heel snelle generator gebracht: de SplittableRandom klasse.

Zoals we kunnen zien in JavaDoc, is dit een generator voor gebruik in parallelle berekeningen. Het is belangrijk om te weten dat de instanties niet thread-safe zijn. We moeten dus voorzichtig zijn bij het gebruik van deze les.

We hebben de volgendeInt en ints methoden. Met volgendeInt we kunnen direct het bovenste en onderste bereik instellen met behulp van de twee parameters die worden aangeroepen:

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

Deze manier van gebruiken controleert dat de max. hoogte parameter is groter dan min. Anders krijgen we een IllegalArgumentException. Het controleert echter niet of we met positieve of negatieve getallen werken. Elk van de parameters kan dus negatief zijn. We hebben ook beschikbare aanroepen van één en nul parameters. Die werken op dezelfde manier als we eerder hebben beschreven.

We hebben de ints methoden ook. Dit betekent dat we gemakkelijk een stroom kunnen krijgen van int waarden. Ter verduidelijking: we kunnen ervoor kiezen om een ​​beperkte of onbeperkte stream te hebben. Voor een beperkte stream kunnen we de boven- en onderkant instellen voor het nummergeneratiebereik:

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

2.5. java.security.SecureRandom

Als we beveiligingsgevoelige applicaties hebben, zouden we moeten overwegen om SecureRandom. Dit is een cryptografisch sterke generator. Standaard geconstrueerde instanties gebruiken geen cryptografisch willekeurige zaden. Dus we moeten ofwel:

  • Stel het zaadje in - bijgevolg zal het zaad onvoorspelbaar zijn
  • Stel de java.util.secureRandomSeed systeemeigenschap naar waar

Deze klasse erft van java.util.Random. We hebben dus alle methoden beschikbaar die we hierboven hebben gezien. Als we bijvoorbeeld een van de int waarden, dan bellen we volgendeInt zonder parameters:

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

Aan de andere kant, als we het bereik moeten instellen, kunnen we dit noemen met de gebonden parameter:

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

We moeten niet vergeten dat deze manier van gebruiken werpt IllegalArgumentException als de parameter niet groter is dan nul.

3. Gebruik van API's van derden

Zoals we hebben gezien, biedt Java ons veel klassen en methoden voor het genereren van willekeurige getallen. Er zijn echter ook API's van derden voor dit doel.

We gaan er een paar bekijken.

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

Er zijn veel generatoren in de commons-wiskundebibliotheek van het Apache Commons-project. De gemakkelijkste en waarschijnlijk de meest bruikbare is de RandomDataGenerator. Het maakt gebruik van de Goed19937c algoritme voor de willekeurige generatie. We kunnen echter onze algoritme-implementatie leveren.

Laten we eens kijken hoe we het kunnen gebruiken. Ten eerste moeten we afhankelijkheid toevoegen:

 org.apache.commons commons-math3 3.6.1 

De nieuwste versie van commons-math3 is te vinden op Maven Central.

Dan kunnen we ermee aan de slag:

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

3.2. it.unimi.dsi.util.XoRoShiRo128PlusRandom

Dit is zeker een van de snelste implementaties van de generator voor willekeurige getallen. Het is ontwikkeld op de afdeling Informatiewetenschappen van de Universiteit van Milaan.

De bibliotheek is ook beschikbaar bij Maven Central-repositories. Dus laten we de afhankelijkheid toevoegen:

 it.unimi.dsi dsiutils 2.6.0 

Deze generator erft van java.util.Random. Als we echter naar JavaDoc kijken, realiseren we ons dat er maar één manier is om het te gebruiken - via het volgendeInt methode. Bovenal is deze methode alleen beschikbaar met de aanroepen van nul en één parameter. Elk van de andere aanroepen zal direct de java.util.Random methoden.

Als we bijvoorbeeld een willekeurig getal binnen een bereik willen krijgen, schrijven we:

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

4. Conclusie

Er zijn verschillende manieren om het genereren van willekeurige getallen te implementeren. Er is echter geen beste manier. Daarom moeten we degene kiezen die het beste bij onze behoeften past.

Het volledige voorbeeld is te vinden op GitHub.