Hogyan generáljunk véletlen számot Java

⚡ Okos összefoglaló

Véletlenszerű számok Java négy kapcsolódó szabványos könyvtári opcióból származnak: a Random osztályból, a Math.randomból, a ThreadLocalRandomból és a SecureRandomból, amelyek mindegyike a sebesség, a szálbiztonság és a kriptográfiai erősség eltérő keverékét fedi le valós alkalmazásokhoz.

  • 🎲 Véletlenszerű osztály: A java.util.Random függvény elérhetővé teszi a nextInt, nextLong és next függvényeket.Double, és a nextBoolean a gyakori primitív típusokhoz.
  • 🧮 Math.random: A Math.random függvény egy megosztott Random példányt használva dupla értéket ad vissza 0.0 (beleértve) és 1.0 (kizárva) között.
  • 🎯 Egyéni tartományok: Adjon át egy korlátot a nextInt-nek, vagy skálázza a Math.random-ot, hogy a minimum és maximum értékek között legyen.
  • 🧵 Menetbiztonság: A java.util.concurrent fájlban található ThreadLocalRandom függvény minden szálnak saját generátort ad, és versenyhelyzetben felülmúlja a megosztott Random függvényt.
  • 🔐 Biztonság: A java.security SecureRandom függvénye kriptográfiailag erős értékeket állít elő jelszavakhoz, tokenekhez és munkamenet-kulcsokhoz.
  • ???? Reprodukálhatóság: Ha egy véletlenszerű függvényt fix long értékkel vetünk be, a tesztek és szimulációk determinisztikusak lesznek a futtatások között.

Hogyan generáljunk véletlen számot Java

Véletlenszerű számok jelennek meg mindenhol Java, az egységtesztelési adatoktól és a kockadobásos játékoktól kezdve a munkamenet-tokenekig és a kevert paklikig. Ez az oktatóanyag elmagyarázza, hogyan generálhatunk véletlenszámokat a Java a standard könyvtár összes opciójának használata, és a feladathoz megfelelő kiválasztása.

Véletlenszám generálása Java

Az Java A standard könyvtár négy gyakori módszert kínál véletlenszámok generálására:

  • java.util.Random az általános célú osztály. Boolean, int, long, float és double értékeket állít elő olyan metódusok segítségével, mint a nextInt, nextLongés nextDouble.
  • Math.random egy statikus segédfüggvény, amely egy megosztott függvényt használva 0.0 (beleértve) és 1.0 (kizárva) közötti dupla értéket ad vissza. Random belsőleg.
  • ThreadLocalRandom in java.util.concurrent minden szálnak saját generátort ad, így több szál nem verseng egyetlen példányon belül.
  • SecureRandom in java.security kriptográfiailag erős pszeudovéletlenszerű számokat állít elő jelszavakhoz, munkamenet-azonosítókhoz és kulcsokhoz.

Az alábbi szakaszok bemutatják, hogyan generálhatunk tíz véletlenszámot az egyes megközelítésekkel.

Példa: Véletlenszám generálása Java Véletlen osztály

Az első példa a következőt használja: java.util.Random tíz egész szám előállítása 0 és 99 között:

import java.util.Random;

public class RandomNumbers {
    public static void main(String[] args) {
        Random objGenerator = new Random();
        for (int iCount = 0; iCount < 10; iCount++) {
            int randomNumber = objGenerator.nextInt(100);
            System.out.println("Random No : " + randomNumber);
        }
    }
}

output:

Random No : 17
Random No : 57
Random No : 73
Random No : 48
Random No : 68
Random No : 86
Random No : 34
Random No : 97
Random No : 73
Random No : 18

Egy példa Random úgy jön létre, mint objGenerator Az nextInt(int bound) A metódus egy 0 (beleértve) és a megadott korlát (kizáró) közötti értéket ad vissza, tehát nextInt(100) 0 és 99 közötti értékeket ad vissza. A sorozat reprodukálhatóvá tételéhez adjunk át egy seedet a konstruktornak, például new Random(42)ugyanaz a vetőmag mindig ugyanazt a szekvenciát eredményezi, ami hasznos tesztekben és szimulációkban.

Példa: Használata Java Math.random

Tíz véletlenszerű érték generálásához 0.0 és 1.0 között, hívjuk meg a statikus függvényt Math.random módszer egy belül hurokEz a leggyorsabb módja annak, hogy véletlenszerű dupla értéket kapjunk generátor objektum létrehozása nélkül:

public class DemoRandom {
    public static void main(String[] args) {
        for (int xCount = 0; xCount < 10; xCount++) {
            System.out.println(Math.random());
        }
    }
}

output:

0.46518450373334297
0.14859851177803485
0.5628391820492477
0.6323378498048606
0.1740198445692248
0.9140544122258946
0.9167350036262347
0.49251219841030147
0.7426056725722353
0.2039418871298877

a motorháztető alatt, Math.random egyetlen statikus elemet hoz létre Random első használatkor és híváskor nextDouble rajta. Ez az egyetlen megosztott generátor megfelelő a demókhoz, de szűk keresztmetszetet képez nagy többszálú terhelés alatt, amit a következő szakaszok tárgyalnak.

Véletlenszerű szám generálása egyéni tartományban

A valódi programok általában egy adott tartományon belüli véletlenszerű értékre szorulnak, például egy 1 és 6 közötti egész számra egy kockadobáshoz, vagy egy 10.0 és 20.0 közötti dupla értékre egy szimulációhoz. Két minta szinte minden esetet lefed.

Véletlenszerű egész szám a minimum és a maximum között (beleértve):

import java.util.Random;

public class RangeDemo {
    public static void main(String[] args) {
        Random rnd = new Random();
        int min = 1;
        int max = 6;
        // nextInt(max - min + 1) returns 0..(max-min), then shift by min
        int dice = rnd.nextInt(max - min + 1) + min;
        System.out.println("Dice roll : " + dice);
    }
}

Véletlenszerű dupla a min és max között:

double min = 10.0;
double max = 20.0;
double value = min + (max - min) * Math.random();
System.out.println("Value : " + value);

Mindkét minta úgy működik, hogy a generátor natív tartományából vesz egy értéket, azt a céltartomány szélességére méretezi, majd a minimummal felfelé tolja el. Ha bekapcsolva van Java 8-as vagy újabb verzió esetén ugyanaz az eredmény érhető el az újabb verzión keresztül is. ints, longsés doubles stream metódusok bekapcsolva Random, Például rnd.ints(10, 1, 7).forEach(System.out::println) tíz kockadobásért.

ThreadLocalRandom többszálú feldolgozáshoz Code

Egyetlen megosztott Random szálbiztos, de versengés esetén lassú, mivel minden szálnak ugyanazon a belső magon kell szinkronizálódnia. ThreadLocalRandom, hozzáadva Java 7 éves és ott lakik java.util.concurrent, minden szálnak saját generátort ad, így nincs zárolási versengés.

import java.util.concurrent.ThreadLocalRandom;

public class ThreadLocalDemo {
    public static void main(String[] args) {
        // random int in [1, 100]
        int i = ThreadLocalRandom.current().nextInt(1, 101);

        // random long in [1000, 5000]
        long l = ThreadLocalRandom.current().nextLong(1000L, 5001L);

        // random double in [0.0, 1.0)
        double d = ThreadLocalRandom.current().nextDouble();

        System.out.println(i + " " + l + " " + d);
    }
}

Felhasználás ThreadLocalRandom.current() munkaszálakon, párhuzamos adatfolyamokon és bármely egyidejű feladaton belül. Vegye figyelembe, hogy setSeed dob UnsupportedOperationException, tehát a reprodukálhatóság érdekében történő seedelés nem támogatott; ha fix seedre van szüksége, maradjon a sima Random.

SecureRandom a biztonság szempontjából érzékeny véletlenszerűségekhez Numbers

Példányai Random és a ThreadLocalRandom nem kriptográfiailag biztonságosak. Néhány kimeneti minta alapján a támadó rekonstruálhatja a belső állapotot és megjósolhatja a jövőbeli értékeket. Jelszavakhoz, munkamenet-tokenekhez, sóértékekhez és kriptográfiai kulcsokhoz használja a következőt: java.security.SecureRandom ehelyett. Az operációs rendszer entrópiakészletéből merít alapanyagot, és olyan értékeket hoz létre, amelyek ellenállnak a predikciónak.

import java.security.SecureRandom;

public class SecureDemo {
    public static void main(String[] args) {
        SecureRandom secure = new SecureRandom();

        byte[] token = new byte[16];
        secure.nextBytes(token);          // 128-bit random token

        int otp = secure.nextInt(1_000_000); // 6-digit one-time code

        System.out.println("OTP : " + String.format("%06d", otp));
    }
}

SecureRandom lassabb, mint Random mert erősebb algoritmusokat és gazdagabb alapanyagot használ. Tartsd fenn biztonsági munkákhoz, és használd a gyorsabb generátorokat játékokhoz, szimulációkhoz és tesztadatokhoz.

GYIK

Hozz létre egy java.util.Random példányt, és hívd meg a nextInt, nextLong és next függvényeket.Double, vagy nextBoolean. Egy gyors egysoros megoldáshoz használd a Math.random függvényt, amely egy 0.0 és 1.0 közötti dupla értéket ad vissza. Mindkét megközelítés a standard könyvtár része.

Egész számok esetén hívd meg a random.nextInt(max – min + 1) + min, dupla számok esetén pedig a min + (max – min) * Math.random() függvényt. A képletek a generátor tartományát a célablak méretéhez igazítják, és a minimális értékkel eltolják.

A Random egy teljes értékű osztály, amely számos primitív típus metódusait tartalmazza, és támogatja a seeding (szintezelést). A Math.random egy statikus segítő, amely 0.0 és 1.0 közötti dupla értéket ad vissza. Belsőleg a Math.random egyetlen megosztott Random példányt hív meg.

Igen, de az egyidejű hívások ugyanazon a belső seeden versengenek, ami lelassítja a sűrűn szálazott kódot. Használd a java.util.concurrent ThreadLocalRandom.current() függvényét, hogy minden szálnak saját generátora legyen, és megszüntesd ezt a versengést.

Adj át egy fix long értéket a Random konstruktornak, például new Random(42)-t, vagy hívd meg a setSeed(42) függvényt. A generátor minden futáskor ugyanazt a sorozatot fogja előállítani, ami elengedhetetlen az ismételhető tesztekhez és szimulációkhoz.

Használja a SecureRandom módszert, ha az értéknek ellen kell állnia a predikciónak, például jelszavak, munkamenet-tokenek, sóértékek, egyszer használatos kódok és kriptográfiai kulcsok esetén. A Plain Random gyors, de kiszámítható, így biztonsági munkához nem biztonságos.

A gépi tanulási keretrendszerek pszeudo-véletlenszerű generátorokat használnak a súlyok inicializálásához, a betanítási adatok összekeveréséhez és az érvényesítési halmazok felosztásához. Egy kezdőérték rögzítése reprodukálhatóvá teszi a kísérleteket, így a csapatok megbízhatóan összehasonlíthatják a modellfutásokat és hibakereshetik az eredményeket.

Igen. A GitHub Copilot Random, ThreadLocalRandom és SecureRandom kódrészleteket állít össze, illeszti a tartományskálázási képleteket, és JUnit tesztek. RevTekintse át az egyes javaslatokat, hogy megbizonyosodjon arról, hogy a kiválasztott osztály megfelel a használati esetnek, különösen a biztonság szempontjából érzékeny kódok esetében.

Foglald össze ezt a bejegyzést a következőképpen: