Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating a list of random Integers in Java (in a Scala-like fashion)

Tags:

java

java-8

scala

Is there an equivalent in Java 8 or later to the following in Scala?

Seq.fill(n)(Random.nextInt)
like image 289
Daniel Avatar asked Apr 03 '18 00:04

Daniel


2 Answers

You can use Random.ints(n) to generate n random numbers. To avoid boxing, you probably want to put them into an array:

int[] seq = rnd.ints(n).toArray();

If you want a list and you don't mind boxing, you can do this:

List<Integer> list = rnd.ints(n).boxed().collect(toList());

The pseudorandom number generator defined by java.util.Random is used if rnd is an instance of that class. This should be fine for most purposes. If you want to use a different source of randomness, you can override Random.next(bits) to supply bits from a custom source instead of from the built-in generator. For example, you can do this:

WARNING: THIS IS A TERRIBLE SOURCE OF PSEUDORANDOM NUMBERS. DON'T USE IT. THIS IS JUST AN EXAMPLE.

class MyRandom extends Random {
    int state = 0;
    protected int next(int bits) {
        return state ^= 1;
    }
}

Random rnd = new MyRandom();
int[] seq = rnd.ints(n).toArray();

This lets you use your own source of random bits using the API of java.util.Random, such as the ability to get values of various primitives, in different distributions, and streams of different types, ranges, and lengths.

like image 65
Stuart Marks Avatar answered Nov 08 '22 07:11

Stuart Marks


Maybe somewhat closer approximation than Random.ints() would be something like this:

Stream
  .generate(rnd::nextInt)
  .limit(n)
  .collect(toList());

It is "closer" in the sense that, if one ignores minor syntactic differences and Seq vs. List distinction, both the Scala version and this version unify with a function of signature

(Int, Unit => T) => Seq[T]

for any T:

(n, f) => Stream.generate(f).limit(n).collect(toList())
(n, f) => Seq.fill(n)(f)

Unlike Random.ints(), this version works for more complex distributions, and it actually limits the length to some number n, just like the Scala version does. Depending on what you want to do with it, you can collect it to some other data structure, or just leave it as Stream.


Full demo with all imports:

import java.util.stream.*;
import java.util.Random;
import java.util.List;
import static java.util.stream.Collectors.toList;

public class RandomListGeneration {
    public static void main(String args[]) {
        Random rnd = new Random();
        int n = 42;
        List<Integer> result = Stream
            .generate(rnd::nextInt)
            .limit(n)
            .collect(toList());
        System.out.println(result);
    }
}
like image 4
Andrey Tyukin Avatar answered Nov 08 '22 07:11

Andrey Tyukin