Jak wygenerować liczbę losową w Java
⚡ Inteligentne podsumowanie
Liczby losowe w Java pochodzą z czterech powiązanych ze sobą standardowych opcji bibliotecznych: klasy Random, Math.random, ThreadLocalRandom i SecureRandom, z których każda obejmuje inne połączenie szybkości, bezpieczeństwa wątków i siły kryptograficznej dla rzeczywistych zastosowań.
Losowe liczby pojawiają się wszędzie Java, od danych testów jednostkowych i gier z rzutami kośćmi, po żetony sesji i tasowane talie. Ten samouczek wyjaśnia, jak generować liczby losowe w Java jak korzystać z każdej opcji dostępnej w bibliotece standardowej i jak wybrać tę właściwą do danego zadania.
Wygeneruj liczbę losową w Java
Java Biblioteka standardowa oferuje cztery popularne sposoby generowania liczb losowych:
java.util.Randomto klasa ogólnego przeznaczenia. Generuje wartości typu boolean, int, long, float i double za pomocą metod takich jaknextInt,nextLong,nextDouble.Math.randomjest statycznym pomocnikiem, który zwraca wartość typu double między 0.0 (włącznie) a 1.0 (wyłącznie) przy użyciu współdzielonegoRandomwewnętrznie.ThreadLocalRandominjava.util.concurrentnadaje każdemu wątkowi własny generator, dzięki czemu wiele wątków nie rywalizuje ze sobą na jednym wystąpieniu.SecureRandominjava.securitygeneruje kryptograficznie silne pseudolosowe liczby dla haseł, identyfikatorów sesji i kluczy.
Poniższe sekcje pokazują, jak wygenerować dziesięć liczb losowych przy użyciu każdej metody.
Przykład: Generowanie liczb losowych za pomocą Java Losowa klasa
W pierwszym przykładzie użyto java.util.Random aby wygenerować dziesięć liczb całkowitych z zakresu od 0 do 99 włącznie:
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); } } }
Wyjście:
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
Przypadek Random jest stworzony jako objGenerator, nextInt(int bound) metoda zwraca wartość pomiędzy 0 (włącznie) a podaną granicą (bez ograniczeń), więc nextInt(100) zwraca wartości od 0 do 99. Aby sekwencja była powtarzalna, należy przekazać konstruktorowi ziarno, na przykład new Random(42); to samo ziarno zawsze daje tę samą sekwencję, co jest przydatne w testach i symulacjach.
Przykład: użycie Java Matematyka losowa
Aby wygenerować dziesięć losowych wartości z zakresu od 0.0 do 1.0, wywołaj metodę statyczną Math.random metoda wewnątrz pętla. To najszybszy sposób na uzyskanie losowego double'a bez tworzenia obiektu generatora:
public class DemoRandom { public static void main(String[] args) { for (int xCount = 0; xCount < 10; xCount++) { System.out.println(Math.random()); } } }
Wyjście:
0.46518450373334297 0.14859851177803485 0.5628391820492477 0.6323378498048606 0.1740198445692248 0.9140544122258946 0.9167350036262347 0.49251219841030147 0.7426056725722353 0.2039418871298877
Pod maską, Math.random tworzy pojedynczą statyczną Random przy pierwszym użyciu i połączeniach nextDouble Na tym. Ten pojedynczy, współdzielony generator sprawdza się w wersjach demonstracyjnych, ale staje się wąskim gardłem przy dużym obciążeniu wielowątkowym, o czym mowa w kolejnych sekcjach.
Wygeneruj liczbę losową w niestandardowym zakresie
Rzeczywiste programy zazwyczaj wymagają losowej wartości z określonego zakresu, na przykład liczby całkowitej od 1 do 6 w przypadku rzutu kostką lub liczby podwójnej od 10.0 do 20.0 w przypadku symulacji. Dwa wzorce pokrywają niemal każdy przypadek.
Losowa liczba całkowita pomiędzy min. a maks. (włącznie):
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); } }
Losowy dublet pomiędzy min i max:
double min = 10.0; double max = 20.0; double value = min + (max - min) * Math.random(); System.out.println("Value : " + value);
Oba wzorce działają poprzez pobranie wartości z natywnego zakresu generatora, skalowanie jej do szerokości zakresu docelowego i przesunięcie w górę o minimum. Jeśli jesteś na Java 8 lub nowszy, ten sam wynik jest dostępny w nowszej wersji ints, longs, doubles metody strumieniowe na Random, Na przykład rnd.ints(10, 1, 7).forEach(System.out::println) na dziesięć rzutów kostką.
ThreadLocalRandom dla wielowątkowości Code
Pojedynczy wspólny Random jest bezpieczny dla wątków, ale powolny w warunkach rywalizacji, ponieważ każdy wątek musi synchronizować się na tym samym wewnętrznym ziarnie. ThreadLocalRandom, dodane Java 7 i mieszka w java.util.concurrent, daje każdemu wątkowi własny generator, dzięki czemu nie występuje rywalizacja o blokadę.
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); } }
Zastosowanie ThreadLocalRandom.current() wewnątrz wątków roboczych, strumieni równoległych i wszelkich zadań współbieżnych. Należy pamiętać, że setSeed rzuca UnsupportedOperationException, więc nie obsługujemy zasiewania w celu zapewnienia powtarzalności; jeśli potrzebujesz stałego zasiewu, trzymaj się zwykłego Random.
SecureRandom do losowych zapytań wymagających bezpieczeństwa Numbers
przypadki Random oraz ThreadLocalRandom Nie są bezpieczne kryptograficznie. Mając kilka próbek wyjściowych, atakujący może zrekonstruować stan wewnętrzny i przewidzieć przyszłe wartości. W przypadku haseł, tokenów sesji, wartości soli i kluczy kryptograficznych należy użyć java.security.SecureRandom Zamiast tego pobiera materiał z puli entropii systemu operacyjnego i generuje wartości, których nie da się przewidzieć.
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 jest wolniejszy niż Random Ponieważ wykorzystuje silniejsze algorytmy i bogatszy materiał źródłowy. Zarezerwuj go do prac związanych z bezpieczeństwem, a szybsze generatory wykorzystaj do gier, symulacji i danych testowych.

