Hur man genererar slumptal i Java

⚡ Smart sammanfattning

Slumpmässiga tal i Java kommer från fyra relaterade standardbiblioteksalternativ, Random-klassen, Math.random, ThreadLocalRandom och SecureRandom, som var och en täcker en annan blandning av hastighet, trådsäkerhet och kryptografisk styrka för verkliga tillämpningar.

  • 🎲 Slumpmässig klass: java.util.Random exponerar nextInt, nextLong, nextDouble, och nextBoolean för vanliga primitiva typer.
  • 🧮 Math.random: Math.random returnerar en dubbel mellan 0.0 inklusive och 1.0 exklusive med hjälp av en delad Random-instans.
  • 🎯 Anpassade intervall: Skicka en gräns till nextInt eller skala Math.random för att generera värden inom valfritt minimum och maximum.
  • 🧵 Trådsäkerhet: ThreadLocalRandom i java.util.concurrent ger varje tråd sin egen generator och överträffar en delad Random under konkurrens.
  • 🔐 Säkerhet: SecureRandom i java.security producerar kryptografiskt starka värden för lösenord, tokens och sessionsnycklar.
  • ???? reproducerbarhet: Att seedning av en slumpmässig värde med en fast long gör tester och simuleringar deterministiska över körningar.

Hur man genererar slumptal i Java

Slumpmässiga tal dyker upp överallt Java, från enhetstestdata och tärningskastspel till sessionsmarker och blandade kortlekar. Den här handledningen förklarar hur man genererar slumptal i Java använda alla alternativ i standardbiblioteket och hur man väljer rätt för jobbet.

Generera slumptal i Java

Ocuco-landskapet Java Standardbiblioteket erbjuder fyra vanliga sätt att generera ett slumptal:

  • java.util.Random är den generella klassen. Den producerar booleska, int-, long-, float- och double-värden genom metoder som nextInt, nextLongoch nextDouble.
  • Math.random är en statisk hjälpare som returnerar en dubbel mellan 0.0 (inklusive) och 1.0 (exklusive) med hjälp av en delad Random internt.
  • ThreadLocalRandom in java.util.concurrent ger varje tråd sin egen generator, så flera trådar konkurrerar inte om en enda instans.
  • SecureRandom in java.security producerar kryptografiskt starka pseudoslumptal för lösenord, sessionsidentifierare och nycklar.

Avsnitten nedan visar hur man genererar tio slumptal med varje metod.

Exempel: Generera slumptal med hjälp av Java Slumpmässig klass

Det första exemplet använder java.util.Random för att producera tio heltal i intervallet 0 till och med 99:

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);
        }
    }
}

Produktion:

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

Ett exempel på Random skapas som objGenerator. De nextInt(int bound) Metoden returnerar ett värde mellan 0 (inklusive) och den angivna gränsen (exklusive), så nextInt(100) ger värden från 0 till 99. För att göra sekvensen reproducerbar, skicka ett frö till konstruktorn, till exempel new Random(42); samma frö producerar alltid samma sekvens, vilket är användbart i tester och simuleringar.

Exempel: Använda Java Matematik.slumpmässig

För att generera tio slumpmässiga värden i intervallet 0.0 till 1.0, anropa den statiska Math.random metod inuti en slingaDetta är det snabbaste sättet att få en slumpmässig dubbel utan att skapa ett generatorobjekt:

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

Produktion:

0.46518450373334297
0.14859851177803485
0.5628391820492477
0.6323378498048606
0.1740198445692248
0.9140544122258946
0.9167350036262347
0.49251219841030147
0.7426056725722353
0.2039418871298877

Under huven, Math.random skapar en enda statisk Random vid första användningen och samtal nextDouble på den. Den där delade generatorn fungerar bra för demonstrationer men blir en flaskhals under hög flertrådad belastning, vilket nästa avsnitt tar upp.

Generera ett slumptal i ett anpassat område

Verkliga program behöver vanligtvis ett slumpmässigt värde inom ett specifikt intervall, såsom ett heltal mellan 1 och 6 för ett tärningskast eller en dubbel mellan 10.0 och 20.0 för en simulering. Två mönster täcker nästan varje fall.

Slumpmässigt heltal mellan min och max (inklusive):

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);
    }
}

Slumpmässig dubbel mellan min och max:

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

Båda mönstren fungerar genom att ta ett värde från generatorns ursprungliga område, skala det till målområdets bredd och flytta upp det med minimum. Om du är på Java 8 eller senare, samma resultat är tillgängligt via den nyare ints, longsoch doubles strömningsmetoder på Random, till exempel rnd.ints(10, 1, 7).forEach(System.out::println) för tio tärningskast.

ThreadLocalRandom för flertrådad Code

En enda delad Random är trådsäker men långsam under konkurrens eftersom varje tråd måste synkroniseras på samma interna frö. ThreadLocalRandom, lagt till Java 7 och bor i java.util.concurrent, ger varje tråd sin egen generator så att det inte uppstår någon låskonflikt.

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);
    }
}

Använda ThreadLocalRandom.current() inuti arbetstrådar, parallella strömmar och alla samtidiga uppgifter. Observera att setSeed kastar UnsupportedOperationException, så sådd för reproducerbarhet stöds inte; om du behöver ett fast frö, håll dig till vanligt Random.

SecureRandom för säkerhetskänsliga slumpmässiga Numbers

Fall av Random och ThreadLocalRandom är inte kryptografiskt säkra. Med ett fåtal utdataexempel kan en angripare rekonstruera det interna tillståndet och förutsäga framtida värden. För lösenord, sessionstokens, saltvärden och kryptografiska nycklar, använd java.security.SecureRandom istället. Den hämtar frömaterial från operativsystemets entropipool och producerar värden som motstår förutsägelser.

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 är långsammare än Random eftersom den använder starkare algoritmer och rikare frömaterial. Reservera det för säkerhetsarbete och använd de snabbare generatorerna för spel, simuleringar och testdata.

Vanliga frågor

Skapa en java.util.Random-instans och anropa nextInt, nextLong, nextDouble, eller nextBoolean. För en snabb sammanfattning, använd Math.random som returnerar ett dubbelvärde mellan 0.0 och 1.0. Båda metoderna levereras med standardbiblioteket.

Anropa random.nextInt(max – min + 1) + min för heltal, eller min + (max – min) * Math.random() för dubbletter. Formlerna skalar generatorns intervall till ditt målfönster och förskjuts med minimivärdet.

Random är en komplett klass med metoder för många primitiva typer och stöder seeding. Math.random är en statisk hjälpare som returnerar en double mellan 0.0 och 1.0. Internt anropar Math.random en enda delad Random-instans.

Ja, men samtidiga anrop konkurrerar med samma interna seed, vilket saktar ner kod med hög trådning. Använd ThreadLocalRandom.current() från java.util.concurrent för att ge varje tråd en egen generator och ta bort den konflikten.

Skicka ett fast long-värde till Random-konstruktorn, till exempel new Random(42), eller anropa setSeed(42). Generatorn kommer att producera samma sekvens varje körning, vilket är viktigt för repeterbara tester och simuleringar.

Använd SecureRandom närhelst värdet måste motstå förutsägelse, till exempel lösenord, sessionstokens, saltvärden, engångskoder och kryptografiska nycklar. Plain Random är snabbt men förutsägbart, så det är osäkert för säkerhetsarbete.

Maskininlärningsramverk använder pseudo-slumpmässiga generatorer för att initiera vikter, blanda träningsdata och dela valideringsmängder. Att fixa ett frö gör experiment reproducerbara så att team kan jämföra modellkörningar och felsöka resultat på ett tillförlitligt sätt.

Ja. GitHub Copilot använder Random-, ThreadLocalRandom- och SecureRandom-kodavsnitt, matchande formler för skalning av intervall och JUnit tester. RevVisa varje förslag för att bekräfta att den valda klassen passar användningsfallet, särskilt för säkerhetskänslig kod.

Sammanfatta detta inlägg med: