randomness in the air

Written on May 5, 2025

Java’s Random class provides a way to generate random numbers and is commonly used in various applications. This article explores the capabilities of the Random class, its methods, and practical examples of its usage.

Table of Contents

  1. Basic Usage
  2. Core Methods
  3. Advanced Features
  4. Best Practices
  5. Common Use Cases
  6. Performance Considerations

Basic Usage

The Random class is part of the java.util package and provides methods to generate random numbers of different types. Here’s a basic example:

import java.util.Random;

public class RandomExample {
    public static void main(String[] args) {
        // Create a new Random instance
        Random random = new Random();
        
        // Generate a random integer
        int randomInt = random.nextInt();
        System.out.println("Random integer: " + randomInt);
        
        // Generate a random integer between 0 (inclusive) and 100 (exclusive)
        int randomRange = random.nextInt(100);
        System.out.println("Random integer between 0 and 100: " + randomRange);
    }
}

Core Methods

The Random class provides several methods for generating random values:

1. Integer Generation

Random random = new Random();

// Generate any random integer
int anyInt = random.nextInt();

// Generate random integer in range [0, bound)
int boundedInt = random.nextInt(100);  // 0 to 99

// Generate random integer in range [min, max]
int min = 10;
int max = 20;
int rangeInt = random.nextInt(max - min + 1) + min;

2. Double Generation

Random random = new Random();

// Generate random double between 0.0 (inclusive) and 1.0 (exclusive)
double randomDouble = random.nextDouble();

// Generate random double in range [min, max]
double min = 10.0;
double max = 20.0;
double rangeDouble = min + (max - min) * random.nextDouble();

3. Boolean Generation

Random random = new Random();

// Generate random boolean (true or false)
boolean randomBoolean = random.nextBoolean();

4. Long Generation

Random random = new Random();

// Generate random long
long randomLong = random.nextLong();

// Generate random long in range [0, bound)
long boundedLong = random.nextLong(1000);

5. Float Generation

Random random = new Random();

// Generate random float between 0.0 and 1.0
float randomFloat = random.nextFloat();

6. Gaussian (Normal) Distribution

Random random = new Random();

// Generate random number with Gaussian distribution
// Mean = 0.0, Standard Deviation = 1.0
double gaussian = random.nextGaussian();

// Generate Gaussian with custom mean and standard deviation
double mean = 100.0;
double stdDev = 15.0;
double customGaussian = mean + stdDev * random.nextGaussian();

Advanced Features

1. Seeding

You can provide a seed to get reproducible random sequences:

// Create Random with specific seed
Random seededRandom = new Random(12345L);

// Will generate the same sequence every time
System.out.println(seededRandom.nextInt());  // Always same value
System.out.println(seededRandom.nextInt());  // Always same value

2. Stream Generation

Java 8+ allows generating streams of random numbers:

Random random = new Random();

// Generate stream of random integers
IntStream randomInts = random.ints(5);  // 5 random integers
randomInts.forEach(System.out::println);

// Generate stream of random doubles
DoubleStream randomDoubles = random.doubles(5, 0.0, 1.0);  // 5 random doubles between 0 and 1
randomDoubles.forEach(System.out::println);

3. Thread Safety

The Random class is thread-safe, but for better performance in multi-threaded applications, consider using ThreadLocalRandom:

// Thread-safe random number generation
int threadSafeRandom = ThreadLocalRandom.current().nextInt(100);

Best Practices

  1. Reuse Random Instances:
    // Good: Reuse the same instance
    private static final Random RANDOM = new Random();
       
    public void method() {
        int random = RANDOM.nextInt(100);
    }
       
    // Bad: Creating new instance each time
    public void method() {
        Random random = new Random();  // Don't do this
        int random = random.nextInt(100);
    }
    
  2. Use Appropriate Bounds:
    // Good: Clear bounds
    int random = random.nextInt(max - min + 1) + min;
       
    // Bad: Unclear bounds
    int random = random.nextInt(max) + min;  // Might not give desired range
    
  3. Consider ThreadLocalRandom for Multi-threading:
    // Good for multi-threaded applications
    int random = ThreadLocalRandom.current().nextInt(100);
    

Common Use Cases

1. Random Selection from Collection

List<String> items = Arrays.asList("A", "B", "C", "D");
Random random = new Random();

// Get random item
String randomItem = items.get(random.nextInt(items.size()));

2. Shuffling Array

int[] array = {1, 2, 3, 4, 5};
Random random = new Random();

// Fisher-Yates shuffle
for (int i = array.length - 1; i > 0; i--) {
    int j = random.nextInt(i + 1);
    // Swap
    int temp = array[i];
    array[i] = array[j];
    array[j] = temp;
}

3. Password Generation

public String generatePassword(int length) {
    String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()";
    Random random = new Random();
    StringBuilder password = new StringBuilder();
    
    for (int i = 0; i < length; i++) {
        password.append(chars.charAt(random.nextInt(chars.length())));
    }
    
    return password.toString();
}

4. Random Sampling

public List<Integer> randomSample(List<Integer> population, int sampleSize) {
    Random random = new Random();
    List<Integer> sample = new ArrayList<>();
    List<Integer> temp = new ArrayList<>(population);
    
    for (int i = 0; i < sampleSize && !temp.isEmpty(); i++) {
        int index = random.nextInt(temp.size());
        sample.add(temp.remove(index));
    }
    
    return sample;
}

Performance Considerations

  1. Random vs ThreadLocalRandom:
    • Use Random for single-threaded applications
    • Use ThreadLocalRandom for multi-threaded applications
    • Use SecureRandom for cryptographic operations
  2. Memory Usage:
    • Random instances are lightweight
    • Reuse instances instead of creating new ones
    • Consider using static final instances
  3. CPU Usage:
    • Random number generation is CPU-intensive
    • Cache random numbers if possible
    • Use appropriate bounds to avoid unnecessary calculations

Conclusion

The Random class in Java provides a robust and flexible way to generate random numbers. Understanding its capabilities and best practices helps in writing efficient and correct random number generation code. Choose the appropriate method based on your specific needs, considering factors like thread safety, performance, and the type of random numbers required.

References

  1. Java Documentation: Random Class
  2. Java Documentation: ThreadLocalRandom Class
  3. Java Documentation: SecureRandom Class