# Stream-Based Linear Congruential Generator in Java 8

A while ago, I wrote a post on a Stream-Based Linear Congruential Generator in Scala. This post is a similar implementation using the Java 8 Stream API.

Here is a Java 8 stream-based implementation of a pseudo-random number generator using a linear congruential generator (LCG):

package com.michaelcotterell.util;

import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;

public class Random {

private final long a;    // multiplier
private final long c;    // increment
private final long m;    // modulus
private final long seed; // start value

private final LongStream stream;

public Random(long a, long c, long m, long seed) {
this.a      = a;
this.c      = c;
this.m      = m;
this.seed   = seed % m;
this.stream = LongStream.iterate(this.seed, x -> (a * x + c) % m);
} // Random

public Random(long a, long c, long m) {
this(a, c, m, System.currentTimeMillis());
} // Random

public LongStream longs() {
return stream.map(e -> e);
} // longs

public IntStream ints() {
return stream.mapToInt(e -> (int) (e % (Integer.MAX_VALUE + 1L)));
} // ints

public DoubleStream doubles() {
final double ONE_OVER_M = 1.0 / m;
return stream.mapToDouble(e -> e * ONE_OVER_M);
} // doubles

} // Random

To use this class, you might do something like the following:

Random lcg = new Random(48271, 0, (2L << 31) - 1, System.currentTimeMillis());
Iterator<Double> rand = lcg.doubles().iterator();

for (int i = 0; i < 10; ++i) System.out.println(rand.next()); 

To test different LCGs, you might do the following:

long iters = 100_000;
long seed  = System.currentTimeMillis();

Random[] lcgs = new Random[] {
new Random(48271, 0, (2L << 31) - 1, seed), // MINSTD (updated)
new Random(16807, 0, (2L << 31) - 1, seed), // MINSTD (old)
new Random(65539, 0, (2L << 31),     seed)  // RANDU
};

for (Random lcg : lcgs) {
System.out.println(lcg.doubles().limit(iters).summaryStatistics());
} // for