Jak vygenerovat náhodné číslo v Java
⚡ Chytré shrnutí
Náhodná čísla v Java pocházejí ze čtyř souvisejících možností standardní knihovny, třídy Random, Math.random, ThreadLocalRandom a SecureRandom, přičemž každá z nich pokrývá jinou kombinaci rychlosti, bezpečnosti vláken a kryptografické síly pro reálné aplikace.

Náhodná čísla se objevují všude Java, od dat z jednotkových testů a her s hodem kostkami až po žetony relací a zamíchané balíčky. Tento tutoriál vysvětluje, jak generovat náhodná čísla v Java použití všech možností ve standardní knihovně a jak vybrat tu správnou pro daný úkol.
Generovat náhodné číslo v Java
Jedno Java Standardní knihovna nabízí čtyři běžné způsoby generování náhodných čísel:
java.util.Randomje univerzální třída. Vytváří hodnoty typu boolean, int, long, float a double pomocí metod, jako napříkladnextInt,nextLong, anextDouble.Math.randomje statický pomocník, který vrací hodnotu typu double mezi 0.0 (včetně) a 1.0 (bez ní) pomocí sdílené metody.Randomvnitřně.ThreadLocalRandominjava.util.concurrentdává každému vláknu vlastní generátor, takže více vláken nesoupeří v jedné instanci.SecureRandominjava.securityvytváří kryptograficky silná pseudonáhodná čísla pro hesla, identifikátory relací a klíče.
Níže uvedené části ukazují, jak pomocí každého přístupu vygenerovat deset náhodných čísel.
Příklad: Generování náhodných čísel pomocí Java Náhodná třída
První příklad používá java.util.Random pro vytvoření deseti celých čísel v rozsahu 0 až 99 včetně:
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); } } }
Výstup:
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
Příklad Random je vytvořen jako objGenerator, nextInt(int bound) Metoda vrací hodnotu mezi 0 (včetně) a zadanou hranicí (exkluzivní), takže nextInt(100) vrací hodnoty od 0 do 99. Aby byla sekvence reprodukovatelná, předejte konstruktoru například seed. new Random(42); stejné seed vždy produkuje stejnou sekvenci, což je užitečné v testech a simulacích.
Příklad: Použití Java Matematika.náhodná
Pro vygenerování deseti náhodných hodnot v rozsahu 0.0 až 1.0 zavolejte funkci static Math.random metoda uvnitř smyčkaToto je nejrychlejší způsob, jak získat náhodný double bez vytvoření objektu generátoru:
public class DemoRandom { public static void main(String[] args) { for (int xCount = 0; xCount < 10; xCount++) { System.out.println(Math.random()); } } }
Výstup:
0.46518450373334297 0.14859851177803485 0.5628391820492477 0.6323378498048606 0.1740198445692248 0.9140544122258946 0.9167350036262347 0.49251219841030147 0.7426056725722353 0.2039418871298877
pod kapotou, Math.random vytváří jeden statický Random při prvním použití a hovorech nextDouble na tom. Tento jeden sdílený generátor je pro dema v pořádku, ale při velkém vícevláknovém zatížení se stává úzkým hrdlem, o čemž se budeme zabývat v následujících částech.
Generování náhodného čísla ve vlastním rozsahu
Reálné programy obvykle potřebují náhodnou hodnotu v určitém rozsahu, například celé číslo mezi 1 a 6 pro hod kostkou nebo dvojnásobek mezi 10.0 a 20.0 pro simulaci. Dva vzory pokrývají téměř každý případ.
Náhodné celé číslo mezi minimem a maximem (včetně):
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); } }
Náhodné double mezi minimem a maximem:
double min = 10.0; double max = 20.0; double value = min + (max - min) * Math.random(); System.out.println("Value : " + value);
Oba vzory fungují tak, že vezmou hodnotu z nativního rozsahu generátoru, upraví ji na šířku cílového rozsahu a posunou ji nahoru o minimum. Pokud jste na Java 8 nebo novější, stejný výsledek je k dispozici i v novější verzi ints, longs, a doubles metody streamu na Random, Například rnd.ints(10, 1, 7).forEach(System.out::println) pro deset hodů kostkou.
ThreadLocalRandom pro vícevláknové zpracování Code
Jeden sdílený Random je vláknově bezpečné, ale pomalé v případě soupeření, protože každé vlákno se musí synchronizovat na stejném interním semenu. ThreadLocalRandom, přidáno v Java 7 a žijící v java.util.concurrent, dává každému vláknu vlastní generátor, takže nedochází k žádnému soupeření o zámky.
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); } }
Použijte ThreadLocalRandom.current() uvnitř pracovních vláken, paralelních streamů a jakékoli souběžné úlohy. Všimněte si, že setSeed hodí UnsupportedOperationException, takže seedování pro reprodukovatelnost není podporováno; pokud potřebujete fixní seed, držte se prostého Random.
SecureRandom pro náhodné výběry citlivé na zabezpečení Numbers
Případy Random a ThreadLocalRandom nejsou kryptograficky bezpečné. Na základě několika výstupních vzorků může útočník rekonstruovat vnitřní stav a předpovědět budoucí hodnoty. Pro hesla, tokeny relací, hodnoty salt a kryptografické klíče použijte java.security.SecureRandom Místo toho čerpá semenný materiál z entropického fondu operačního systému a produkuje hodnoty, které odolávají predikci.
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 je pomalejší než Random protože používá silnější algoritmy a bohatší seedmaterial. Vyhraďte si ho pro bezpečnostní práce a rychlejší generátory použijte pro hry, simulace a testovací data.
