Cómo generar números aleatorios en Java

⚡ Resumen inteligente

Números aleatorios en Java Provienen de cuatro opciones relacionadas de la biblioteca estándar: la clase Random, Math.random, ThreadLocalRandom y SecureRandom, cada una de las cuales ofrece una combinación diferente de velocidad, seguridad de subprocesos y solidez criptográfica para aplicaciones reales.

  • 🎲 Clase aleatoria: java.util.Random expone nextInt, nextLong, nextDoubley nextBoolean para tipos primitivos comunes.
  • 🧮 Matemáticas aleatorias: Math.random devuelve un número decimal entre 0.0 (inclusive) y 1.0 (exclusivo) utilizando una instancia compartida de Random.
  • 🎯 Gamas personalizadas: Pasa un límite a nextInt o escala Math.random para generar valores dentro de cualquier mínimo y máximo.
  • 🧵 Seguridad de la rosca: ThreadLocalRandom en java.util.concurrent le da a cada hilo su propio generador y supera en rendimiento a un generador aleatorio compartido en situaciones de contención.
  • 🔐 Seguridad: La función SecureRandom de java.security genera valores criptográficamente seguros para contraseñas, tokens y claves de sesión.
  • ???? Repetibilidad: Inicializar una variable aleatoria con un valor fijo de longitud hace que las pruebas y simulaciones sean deterministas en todas las ejecuciones.

Cómo generar números aleatorios en Java

Los números aleatorios aparecen en todas partes Java, desde datos de pruebas unitarias y juegos de dados hasta fichas de sesión y mazos barajados. Este tutorial explica cómo generar números aleatorios en Java Utilizar todas las opciones de la biblioteca estándar y cómo elegir la más adecuada para cada tarea.

Generar números aleatorios en Java

El Java La biblioteca estándar ofrece cuatro formas comunes de generar un número aleatorio:

  • java.util.Random es la clase de propósito general. Produce valores booleanos, enteros, largos, flotantes y dobles a través de métodos como nextInt, nextLong, y nextDouble.
  • Math.random es una función auxiliar estática que devuelve un valor double entre 0.0 (inclusive) y 1.0 (exclusivo) utilizando una función compartida Random internamente.
  • ThreadLocalRandom in java.util.concurrent Cada hilo tiene su propio generador, por lo que varios hilos no compiten por una misma instancia.
  • SecureRandom in java.security Genera números pseudoaleatorios criptográficamente seguros para contraseñas, identificadores de sesión y claves.

Las secciones siguientes muestran cómo generar diez números aleatorios con cada método.

Ejemplo: Generar un número aleatorio usando Java Clase aleatoria

El primer ejemplo utiliza java.util.Random para producir diez números enteros en el rango de 0 a 99 inclusive:

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

Salida:

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

Una instancia de Random se crea como objGenerator. La función de nextInt(int bound) El método devuelve un valor entre 0 (inclusive) y el límite proporcionado (exclusivo), por lo que nextInt(100) produce valores de 0 a 99. Para que la secuencia sea reproducible, pase una semilla al constructor, por ejemplo new Random(42); la misma semilla siempre produce la misma secuencia, lo cual es útil en pruebas y simulaciones.

Ejemplo: Uso Java Matemáticas aleatorias

Para generar diez valores aleatorios en el rango de 0.0 a 1.0, llame a la función estática. Math.random método dentro de un loopsEsta es la forma más rápida de obtener un número doble aleatorio sin crear un objeto generador:

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

Salida:

0.46518450373334297
0.14859851177803485
0.5628391820492477
0.6323378498048606
0.1740198445692248
0.9140544122258946
0.9167350036262347
0.49251219841030147
0.7426056725722353
0.2039418871298877

Bajo el capó, Math.random crea un único estático Random en el primer uso y llamadas nextDouble En ello. Ese generador compartido único está bien para demostraciones, pero se convierte en un cuello de botella bajo una carga multihilo pesada, tema que se aborda en las siguientes secciones.

Generar un número aleatorio en un rango personalizado.

Los programas reales suelen necesitar un valor aleatorio dentro de un rango específico, como un número entero entre 1 y 6 para una tirada de dados o un número decimal entre 10.0 y 20.0 para una simulación. Dos patrones cubren casi todos los casos.

Número entero aleatorio entre min y max (inclusive):

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úmero doble aleatorio entre mínimo y máximo:

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

Ambos patrones funcionan tomando un valor del rango nativo del generador, escalándolo al ancho del rango objetivo y desplazándolo hacia arriba en el mínimo. Si estás en Java 8 o posterior, el mismo resultado está disponible a través de la versión más reciente. ints, longs, y doubles métodos de flujo en Random, Por ejemplo rnd.ints(10, 1, 7).forEach(System.out::println) para diez tiradas de dados.

ThreadLocalRandom para multihilo Code

Un único compartido Random Es seguro para subprocesos, pero lento en situaciones de contención porque cada subproceso tiene que sincronizarse con la misma semilla interna. ThreadLocalRandom, añadido en Java 7 y viviendo en java.util.concurrentEsto le da a cada hilo su propio generador, por lo que no hay contención de bloqueos.

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

Usar ThreadLocalRandom.current() dentro de los subprocesos de trabajo, flujos paralelos y cualquier tarea concurrente. Tenga en cuenta que setSeed tiros UnsupportedOperationException, por lo que no se admite la inicialización para la reproducibilidad; si necesita una inicialización fija, siga con la inicialización simple. Random.

SecureRandom para generación aleatoria sensible a la seguridad Numbers

Instancias de Random y ThreadLocalRandom no son criptográficamente seguros. Con unas pocas muestras de salida, un atacante puede reconstruir el estado interno y predecir valores futuros. Para contraseñas, tokens de sesión, valores de sal y claves criptográficas, utilice java.security.SecureRandom En cambio, extrae material semilla del conjunto de entropía del sistema operativo y produce valores que se resisten a la predicción.

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 es más lento que Random Porque utiliza algoritmos más robustos y datos de partida más completos. Resérvelo para tareas de seguridad y utilice los generadores más rápidos para juegos, simulaciones y datos de prueba.

Preguntas Frecuentes

Crea una instancia de java.util.Random y llama a nextInt, nextLong, nextDoubleo nextBoolean. Para una solución rápida en una sola línea, use Math.random, que devuelve un número decimal entre 0.0 y 1.0. Ambos métodos vienen incluidos en la biblioteca estándar.

Llama a random.nextInt(max – min + 1) + min para números enteros, o a min + (max – min) * Math.random() para números decimales. Las fórmulas ajustan el rango del generador a la ventana de destino y lo desplazan según el valor mínimo.

Random es una clase completa con métodos para muchos tipos primitivos y admite la inicialización de números. Math.random es una función auxiliar estática que devuelve un valor double entre 0.0 y 1.0. Internamente, Math.random llama a una única instancia compartida de Random.

Sí, pero las llamadas concurrentes compiten por la misma semilla interna, lo que ralentiza el código con muchos hilos. Utilice ThreadLocalRandom.current() de java.util.concurrent para asignar a cada hilo su propio generador y eliminar esa contención.

Pase un valor fijo de tipo long al constructor Random, por ejemplo new Random(42), o llame a setSeed(42). El generador producirá la misma secuencia en cada ejecución, lo cual es esencial para realizar pruebas y simulaciones repetibles.

Utilice SecureRandom siempre que el valor deba resistir la predicción, como en el caso de contraseñas, tokens de sesión, valores de sal, códigos de un solo uso y claves criptográficas. Plain Random es rápido pero predecible, por lo que no es seguro para tareas de seguridad.

Los marcos de aprendizaje automático utilizan generadores pseudoaleatorios para inicializar los pesos, mezclar los datos de entrenamiento y dividir los conjuntos de validación. Fijar una semilla permite que los experimentos sean reproducibles, de modo que los equipos puedan comparar las ejecuciones del modelo y depurar los resultados de forma fiable.

Sí. GitHub Copilot genera fragmentos de código Random, ThreadLocalRandom y SecureRandom, haciendo coincidir las fórmulas de escalado de rango y JUnit pruebas. RevRevise cada sugerencia para confirmar que la clase elegida se ajusta al caso de uso, especialmente para código sensible a la seguridad.

Resumir este post con: